1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #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 #ifdef HAVE_LIMITS_H
59 #include <limits.h>
60 #endif
61 
62 #ifdef USE_LIBIDN
63 #include <idna.h>
64 #include <tld.h>
65 #include <stringprep.h>
66 #ifdef HAVE_IDN_FREE_H
67 #include <idn-free.h>
68 #else
69 /* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
70 void idn_free (void *ptr);
71 #endif
72 #ifndef HAVE_IDN_FREE
73 /* if idn_free() was not found in this version of libidn use free() instead */
74 #define idn_free(x) (free)(x)
75 #endif
76 #elif defined(USE_WIN32_IDN)
77 /* prototype for curl_win32_idn_to_ascii() */
78 bool curl_win32_idn_to_ascii(const char *in, char **out);
79 #endif  /* USE_LIBIDN */
80 
81 #include "urldata.h"
82 #include "netrc.h"
83 
84 #include "formdata.h"
85 #include "vtls/vtls.h"
86 #include "hostip.h"
87 #include "transfer.h"
88 #include "sendf.h"
89 #include "progress.h"
90 #include "cookie.h"
91 #include "strequal.h"
92 #include "strerror.h"
93 #include "escape.h"
94 #include "strtok.h"
95 #include "share.h"
96 #include "content_encoding.h"
97 #include "http_digest.h"
98 #include "http_negotiate.h"
99 #include "select.h"
100 #include "multiif.h"
101 #include "easyif.h"
102 #include "speedcheck.h"
103 #include "rawstr.h"
104 #include "warnless.h"
105 #include "non-ascii.h"
106 #include "inet_pton.h"
107 
108 /* And now for the protocols */
109 #include "ftp.h"
110 #include "dict.h"
111 #include "telnet.h"
112 #include "tftp.h"
113 #include "http.h"
114 #include "http2.h"
115 #include "file.h"
116 #include "curl_ldap.h"
117 #include "ssh.h"
118 #include "imap.h"
119 #include "url.h"
120 #include "connect.h"
121 #include "inet_ntop.h"
122 #include "http_ntlm.h"
123 #include "curl_ntlm_wb.h"
124 #include "socks.h"
125 #include "curl_rtmp.h"
126 #include "gopher.h"
127 #include "http_proxy.h"
128 #include "conncache.h"
129 #include "multihandle.h"
130 #include "pipeline.h"
131 #include "dotdot.h"
132 #include "strdup.h"
133 /* The last 3 #include files should be in this order */
134 #include "curl_printf.h"
135 #include "curl_memory.h"
136 #include "memdebug.h"
137 
138 /* Local static prototypes */
139 static struct connectdata *
140 find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
141                                       struct connectbundle *bundle);
142 static void conn_free(struct connectdata *conn);
143 static void free_fixed_hostname(struct hostname *host);
144 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
145 static CURLcode parse_url_login(struct SessionHandle *data,
146                                 struct connectdata *conn,
147                                 char **userptr, char **passwdptr,
148                                 char **optionsptr);
149 static CURLcode parse_login_details(const char *login, const size_t len,
150                                     char **userptr, char **passwdptr,
151                                     char **optionsptr);
152 static unsigned int get_protocol_family(unsigned int protocol);
153 
154 /*
155  * Protocol table.
156  */
157 
158 static const struct Curl_handler * const protocols[] = {
159 
160 #ifndef CURL_DISABLE_HTTP
161   &Curl_handler_http,
162 #endif
163 
164 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
165   &Curl_handler_https,
166 #endif
167 
168 #ifndef CURL_DISABLE_FTP
169   &Curl_handler_ftp,
170 #endif
171 
172 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
173   &Curl_handler_ftps,
174 #endif
175 
176 #ifndef CURL_DISABLE_TELNET
177   &Curl_handler_telnet,
178 #endif
179 
180 #ifndef CURL_DISABLE_DICT
181   &Curl_handler_dict,
182 #endif
183 
184 #ifndef CURL_DISABLE_LDAP
185   &Curl_handler_ldap,
186 #if !defined(CURL_DISABLE_LDAPS) && \
187     ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
188      (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
189   &Curl_handler_ldaps,
190 #endif
191 #endif
192 
193 #ifndef CURL_DISABLE_FILE
194   &Curl_handler_file,
195 #endif
196 
197 #ifndef CURL_DISABLE_TFTP
198   &Curl_handler_tftp,
199 #endif
200 
201 #ifdef USE_LIBSSH2
202   &Curl_handler_scp,
203   &Curl_handler_sftp,
204 #endif
205 
206 #ifndef CURL_DISABLE_IMAP
207   &Curl_handler_imap,
208 #ifdef USE_SSL
209   &Curl_handler_imaps,
210 #endif
211 #endif
212 
213 #ifndef CURL_DISABLE_POP3
214   &Curl_handler_pop3,
215 #ifdef USE_SSL
216   &Curl_handler_pop3s,
217 #endif
218 #endif
219 
220 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
221    (CURL_SIZEOF_CURL_OFF_T > 4) && \
222    (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
223   &Curl_handler_smb,
224 #ifdef USE_SSL
225   &Curl_handler_smbs,
226 #endif
227 #endif
228 
229 #ifndef CURL_DISABLE_SMTP
230   &Curl_handler_smtp,
231 #ifdef USE_SSL
232   &Curl_handler_smtps,
233 #endif
234 #endif
235 
236 #ifndef CURL_DISABLE_RTSP
237   &Curl_handler_rtsp,
238 #endif
239 
240 #ifndef CURL_DISABLE_GOPHER
241   &Curl_handler_gopher,
242 #endif
243 
244 #ifdef USE_LIBRTMP
245   &Curl_handler_rtmp,
246   &Curl_handler_rtmpt,
247   &Curl_handler_rtmpe,
248   &Curl_handler_rtmpte,
249   &Curl_handler_rtmps,
250   &Curl_handler_rtmpts,
251 #endif
252 
253   (struct Curl_handler *) NULL
254 };
255 
256 /*
257  * Dummy handler for undefined protocol schemes.
258  */
259 
260 static const struct Curl_handler Curl_handler_dummy = {
261   "<no protocol>",                      /* scheme */
262   ZERO_NULL,                            /* setup_connection */
263   ZERO_NULL,                            /* do_it */
264   ZERO_NULL,                            /* done */
265   ZERO_NULL,                            /* do_more */
266   ZERO_NULL,                            /* connect_it */
267   ZERO_NULL,                            /* connecting */
268   ZERO_NULL,                            /* doing */
269   ZERO_NULL,                            /* proto_getsock */
270   ZERO_NULL,                            /* doing_getsock */
271   ZERO_NULL,                            /* domore_getsock */
272   ZERO_NULL,                            /* perform_getsock */
273   ZERO_NULL,                            /* disconnect */
274   ZERO_NULL,                            /* readwrite */
275   0,                                    /* defport */
276   0,                                    /* protocol */
277   PROTOPT_NONE                          /* flags */
278 };
279 
Curl_freeset(struct SessionHandle * data)280 void Curl_freeset(struct SessionHandle *data)
281 {
282   /* Free all dynamic strings stored in the data->set substructure. */
283   enum dupstring i;
284   for(i=(enum dupstring)0; i < STRING_LAST; i++) {
285     Curl_safefree(data->set.str[i]);
286   }
287 
288   if(data->change.referer_alloc) {
289     Curl_safefree(data->change.referer);
290     data->change.referer_alloc = FALSE;
291   }
292   data->change.referer = NULL;
293   if(data->change.url_alloc) {
294     Curl_safefree(data->change.url);
295     data->change.url_alloc = FALSE;
296   }
297   data->change.url = NULL;
298 }
299 
setstropt(char ** charp,const char * s)300 static CURLcode setstropt(char **charp, const char *s)
301 {
302   /* Release the previous storage at `charp' and replace by a dynamic storage
303      copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
304 
305   Curl_safefree(*charp);
306 
307   if(s) {
308     char *str = strdup(s);
309 
310     if(!str)
311       return CURLE_OUT_OF_MEMORY;
312 
313     *charp = str;
314   }
315 
316   return CURLE_OK;
317 }
318 
setstropt_userpwd(char * option,char ** userp,char ** passwdp)319 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
320 {
321   CURLcode result = CURLE_OK;
322   char *user = NULL;
323   char *passwd = NULL;
324 
325   /* Parse the login details if specified. It not then we treat NULL as a hint
326      to clear the existing data */
327   if(option) {
328     result = parse_login_details(option, strlen(option),
329                                  (userp ? &user : NULL),
330                                  (passwdp ? &passwd : NULL),
331                                  NULL);
332   }
333 
334   if(!result) {
335     /* Store the username part of option if required */
336     if(userp) {
337       if(!user && option && option[0] == ':') {
338         /* Allocate an empty string instead of returning NULL as user name */
339         user = strdup("");
340         if(!user)
341           result = CURLE_OUT_OF_MEMORY;
342       }
343 
344       Curl_safefree(*userp);
345       *userp = user;
346     }
347 
348     /* Store the password part of option if required */
349     if(passwdp) {
350       Curl_safefree(*passwdp);
351       *passwdp = passwd;
352     }
353   }
354 
355   return result;
356 }
357 
Curl_dupset(struct SessionHandle * dst,struct SessionHandle * src)358 CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
359 {
360   CURLcode result = CURLE_OK;
361   enum dupstring i;
362 
363   /* Copy src->set into dst->set first, then deal with the strings
364      afterwards */
365   dst->set = src->set;
366 
367   /* clear all string pointers first */
368   memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
369 
370   /* duplicate all strings */
371   for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
372     result = setstropt(&dst->set.str[i], src->set.str[i]);
373     if(result)
374       return result;
375   }
376 
377   /* duplicate memory areas pointed to */
378   i = STRING_COPYPOSTFIELDS;
379   if(src->set.postfieldsize && src->set.str[i]) {
380     /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
381     dst->set.str[i] = Curl_memdup(src->set.str[i],
382                                   curlx_sotouz(src->set.postfieldsize));
383     if(!dst->set.str[i])
384       return CURLE_OUT_OF_MEMORY;
385     /* point to the new copy */
386     dst->set.postfields = dst->set.str[i];
387   }
388 
389   return CURLE_OK;
390 }
391 
392 /*
393  * This is the internal function curl_easy_cleanup() calls. This should
394  * cleanup and free all resources associated with this sessionhandle.
395  *
396  * NOTE: if we ever add something that attempts to write to a socket or
397  * similar here, we must ignore SIGPIPE first. It is currently only done
398  * when curl_easy_perform() is invoked.
399  */
400 
Curl_close(struct SessionHandle * data)401 CURLcode Curl_close(struct SessionHandle *data)
402 {
403   struct Curl_multi *m;
404 
405   if(!data)
406     return CURLE_OK;
407 
408   Curl_expire(data, 0); /* shut off timers */
409 
410   m = data->multi;
411 
412   if(m)
413     /* This handle is still part of a multi handle, take care of this first
414        and detach this handle from there. */
415     curl_multi_remove_handle(data->multi, data);
416 
417   if(data->multi_easy)
418     /* when curl_easy_perform() is used, it creates its own multi handle to
419        use and this is the one */
420     curl_multi_cleanup(data->multi_easy);
421 
422   /* Destroy the timeout list that is held in the easy handle. It is
423      /normally/ done by curl_multi_remove_handle() but this is "just in
424      case" */
425   if(data->state.timeoutlist) {
426     Curl_llist_destroy(data->state.timeoutlist, NULL);
427     data->state.timeoutlist = NULL;
428   }
429 
430   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
431                       the multi handle, since that function uses the magic
432                       field! */
433 
434   if(data->state.rangestringalloc)
435     free(data->state.range);
436 
437   /* Free the pathbuffer */
438   Curl_safefree(data->state.pathbuffer);
439   data->state.path = NULL;
440 
441   /* freed here just in case DONE wasn't called */
442   Curl_free_request_state(data);
443 
444   /* Close down all open SSL info and sessions */
445   Curl_ssl_close_all(data);
446   Curl_safefree(data->state.first_host);
447   Curl_safefree(data->state.scratch);
448   Curl_ssl_free_certinfo(data);
449 
450   /* Cleanup possible redirect junk */
451   free(data->req.newurl);
452   data->req.newurl = NULL;
453 
454   if(data->change.referer_alloc) {
455     Curl_safefree(data->change.referer);
456     data->change.referer_alloc = FALSE;
457   }
458   data->change.referer = NULL;
459 
460   if(data->change.url_alloc) {
461     Curl_safefree(data->change.url);
462     data->change.url_alloc = FALSE;
463   }
464   data->change.url = NULL;
465 
466   Curl_safefree(data->state.headerbuff);
467 
468   Curl_flush_cookies(data, 1);
469 
470   Curl_digest_cleanup(data);
471 
472   Curl_safefree(data->info.contenttype);
473   Curl_safefree(data->info.wouldredirect);
474 
475   /* this destroys the channel and we cannot use it anymore after this */
476   Curl_resolver_cleanup(data->state.resolver);
477 
478   Curl_convert_close(data);
479 
480   /* No longer a dirty share, if it exists */
481   if(data->share) {
482     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
483     data->share->dirty--;
484     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
485   }
486 
487   if(data->set.wildcardmatch) {
488     /* destruct wildcard structures if it is needed */
489     struct WildcardData *wc = &data->wildcard;
490     Curl_wildcard_dtor(wc);
491   }
492 
493   Curl_freeset(data);
494   free(data);
495   return CURLE_OK;
496 }
497 
498 /*
499  * Initialize the UserDefined fields within a SessionHandle.
500  * This may be safely called on a new or existing SessionHandle.
501  */
Curl_init_userdefined(struct UserDefined * set)502 CURLcode Curl_init_userdefined(struct UserDefined *set)
503 {
504   CURLcode result = CURLE_OK;
505 
506   set->out = stdout; /* default output to stdout */
507   set->in_set = stdin;  /* default input from stdin */
508   set->err  = stderr;  /* default stderr to stderr */
509 
510   /* use fwrite as default function to store output */
511   set->fwrite_func = (curl_write_callback)fwrite;
512 
513   /* use fread as default function to read input */
514   set->fread_func_set = (curl_read_callback)fread;
515   set->is_fread_set = 0;
516   set->is_fwrite_set = 0;
517 
518   set->seek_func = ZERO_NULL;
519   set->seek_client = ZERO_NULL;
520 
521   /* conversion callbacks for non-ASCII hosts */
522   set->convfromnetwork = ZERO_NULL;
523   set->convtonetwork   = ZERO_NULL;
524   set->convfromutf8    = ZERO_NULL;
525 
526   set->filesize = -1;        /* we don't know the size */
527   set->postfieldsize = -1;   /* unknown size */
528   set->maxredirs = -1;       /* allow any amount by default */
529 
530   set->httpreq = HTTPREQ_GET; /* Default HTTP request */
531   set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
532   set->ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
533   set->ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
534   set->ftp_use_pret = FALSE;  /* mainly useful for drftpd servers */
535   set->ftp_filemethod = FTPFILE_MULTICWD;
536 
537   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
538 
539   /* Set the default size of the SSL session ID cache */
540   set->ssl.max_ssl_sessions = 5;
541 
542   set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
543   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
544   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
545   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
546 
547   /* make libcurl quiet by default: */
548   set->hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
549 
550   /*
551    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
552    * switched off unless wanted.
553    */
554   set->ssl.verifypeer = TRUE;
555   set->ssl.verifyhost = TRUE;
556 #ifdef USE_TLS_SRP
557   set->ssl.authtype = CURL_TLSAUTH_NONE;
558 #endif
559   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
560                                                       type */
561   set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
562 
563   set->new_file_perms = 0644;    /* Default permissions */
564   set->new_directory_perms = 0755; /* Default permissions */
565 
566   /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
567      define since we internally only use the lower 16 bits for the passed
568      in bitmask to not conflict with the private bits */
569   set->allowed_protocols = CURLPROTO_ALL;
570   set->redir_protocols = CURLPROTO_ALL &  /* All except FILE, SCP and SMB */
571                           ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
572                             CURLPROTO_SMBS);
573 
574 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
575   /*
576    * disallow unprotected protection negotiation NEC reference implementation
577    * seem not to follow rfc1961 section 4.3/4.4
578    */
579   set->socks5_gssapi_nec = FALSE;
580 #endif
581 
582   /* This is our preferred CA cert bundle/path since install time */
583 #if defined(CURL_CA_BUNDLE)
584   result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
585   if(result)
586     return result;
587 #endif
588 #if defined(CURL_CA_PATH)
589   result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
590   if(result)
591     return result;
592 #endif
593 
594   set->wildcardmatch  = FALSE;
595   set->chunk_bgn      = ZERO_NULL;
596   set->chunk_end      = ZERO_NULL;
597 
598   /* tcp keepalives are disabled by default, but provide reasonable values for
599    * the interval and idle times.
600    */
601   set->tcp_keepalive = FALSE;
602   set->tcp_keepintvl = 60;
603   set->tcp_keepidle = 60;
604   set->tcp_fastopen = FALSE;
605 
606   set->ssl_enable_npn = TRUE;
607   set->ssl_enable_alpn = TRUE;
608 
609   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
610   set->sep_headers = TRUE; /* separated header lists by default */
611 
612   Curl_http2_init_userset(set);
613   return result;
614 }
615 
616 /**
617  * Curl_open()
618  *
619  * @param curl is a pointer to a sessionhandle pointer that gets set by this
620  * function.
621  * @return CURLcode
622  */
623 
Curl_open(struct SessionHandle ** curl)624 CURLcode Curl_open(struct SessionHandle **curl)
625 {
626   CURLcode result;
627   struct SessionHandle *data;
628 
629   /* Very simple start-up: alloc the struct, init it with zeroes and return */
630   data = calloc(1, sizeof(struct SessionHandle));
631   if(!data) {
632     /* this is a very serious error */
633     DEBUGF(fprintf(stderr, "Error: calloc of SessionHandle failed\n"));
634     return CURLE_OUT_OF_MEMORY;
635   }
636 
637   data->magic = CURLEASY_MAGIC_NUMBER;
638 
639   result = Curl_resolver_init(&data->state.resolver);
640   if(result) {
641     DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
642     free(data);
643     return result;
644   }
645 
646   /* We do some initial setup here, all those fields that can't be just 0 */
647 
648   data->state.headerbuff = malloc(HEADERSIZE);
649   if(!data->state.headerbuff) {
650     DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
651     result = CURLE_OUT_OF_MEMORY;
652   }
653   else {
654     result = Curl_init_userdefined(&data->set);
655 
656     data->state.headersize=HEADERSIZE;
657 
658     Curl_convert_init(data);
659 
660     /* most recent connection is not yet defined */
661     data->state.lastconnect = NULL;
662 
663     data->progress.flags |= PGRS_HIDE;
664     data->state.current_speed = -1; /* init to negative == impossible */
665 
666     data->wildcard.state = CURLWC_INIT;
667     data->wildcard.filelist = NULL;
668     data->set.fnmatch = ZERO_NULL;
669     data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
670 
671     Curl_http2_init_state(&data->state);
672   }
673 
674   if(result) {
675     Curl_resolver_cleanup(data->state.resolver);
676     free(data->state.headerbuff);
677     Curl_freeset(data);
678     free(data);
679     data = NULL;
680   }
681   else
682     *curl = data;
683 
684   return result;
685 }
686 
Curl_setopt(struct SessionHandle * data,CURLoption option,va_list param)687 CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
688                      va_list param)
689 {
690   char *argptr;
691   CURLcode result = CURLE_OK;
692   long arg;
693 #ifndef CURL_DISABLE_HTTP
694   curl_off_t bigsize;
695 #endif
696 
697   switch(option) {
698   case CURLOPT_DNS_CACHE_TIMEOUT:
699     data->set.dns_cache_timeout = va_arg(param, long);
700     break;
701   case CURLOPT_DNS_USE_GLOBAL_CACHE:
702     /* remember we want this enabled */
703     arg = va_arg(param, long);
704     data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
705     break;
706   case CURLOPT_SSL_CIPHER_LIST:
707     /* set a list of cipher we want to use in the SSL connection */
708     result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
709                        va_arg(param, char *));
710     break;
711 
712   case CURLOPT_RANDOM_FILE:
713     /*
714      * This is the path name to a file that contains random data to seed
715      * the random SSL stuff with. The file is only used for reading.
716      */
717     result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
718                        va_arg(param, char *));
719     break;
720   case CURLOPT_EGDSOCKET:
721     /*
722      * The Entropy Gathering Daemon socket pathname
723      */
724     result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
725                        va_arg(param, char *));
726     break;
727   case CURLOPT_MAXCONNECTS:
728     /*
729      * Set the absolute number of maximum simultaneous alive connection that
730      * libcurl is allowed to have.
731      */
732     data->set.maxconnects = va_arg(param, long);
733     break;
734   case CURLOPT_FORBID_REUSE:
735     /*
736      * When this transfer is done, it must not be left to be reused by a
737      * subsequent transfer but shall be closed immediately.
738      */
739     data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
740     break;
741   case CURLOPT_FRESH_CONNECT:
742     /*
743      * This transfer shall not use a previously cached connection but
744      * should be made with a fresh new connect!
745      */
746     data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
747     break;
748   case CURLOPT_VERBOSE:
749     /*
750      * Verbose means infof() calls that give a lot of information about
751      * the connection and transfer procedures as well as internal choices.
752      */
753     data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
754     break;
755   case CURLOPT_HEADER:
756     /*
757      * Set to include the header in the general data output stream.
758      */
759     data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
760     break;
761   case CURLOPT_NOPROGRESS:
762     /*
763      * Shut off the internal supported progress meter
764      */
765     data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
766     if(data->set.hide_progress)
767       data->progress.flags |= PGRS_HIDE;
768     else
769       data->progress.flags &= ~PGRS_HIDE;
770     break;
771   case CURLOPT_NOBODY:
772     /*
773      * Do not include the body part in the output data stream.
774      */
775     data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
776     break;
777   case CURLOPT_FAILONERROR:
778     /*
779      * Don't output the >=400 error code HTML-page, but instead only
780      * return error.
781      */
782     data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
783     break;
784   case CURLOPT_UPLOAD:
785   case CURLOPT_PUT:
786     /*
787      * We want to sent data to the remote host. If this is HTTP, that equals
788      * using the PUT request.
789      */
790     data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
791     if(data->set.upload) {
792       /* If this is HTTP, PUT is what's needed to "upload" */
793       data->set.httpreq = HTTPREQ_PUT;
794       data->set.opt_no_body = FALSE; /* this is implied */
795     }
796     else
797       /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
798          then this can be changed to HEAD later on) */
799       data->set.httpreq = HTTPREQ_GET;
800     break;
801   case CURLOPT_FILETIME:
802     /*
803      * Try to get the file time of the remote document. The time will
804      * later (possibly) become available using curl_easy_getinfo().
805      */
806     data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
807     break;
808   case CURLOPT_FTP_CREATE_MISSING_DIRS:
809     /*
810      * An FTP option that modifies an upload to create missing directories on
811      * the server.
812      */
813     switch(va_arg(param, long)) {
814     case 0:
815       data->set.ftp_create_missing_dirs = 0;
816       break;
817     case 1:
818       data->set.ftp_create_missing_dirs = 1;
819       break;
820     case 2:
821       data->set.ftp_create_missing_dirs = 2;
822       break;
823     default:
824       /* reserve other values for future use */
825       result = CURLE_UNKNOWN_OPTION;
826       break;
827     }
828     break;
829   case CURLOPT_SERVER_RESPONSE_TIMEOUT:
830     /*
831      * Option that specifies how quickly an server response must be obtained
832      * before it is considered failure. For pingpong protocols.
833      */
834     data->set.server_response_timeout = va_arg(param, long) * 1000;
835     break;
836   case CURLOPT_TFTP_NO_OPTIONS:
837     /*
838      * Option that prevents libcurl from sending TFTP option requests to the
839      * server.
840      */
841     data->set.tftp_no_options = va_arg(param, long) != 0;
842     break;
843   case CURLOPT_TFTP_BLKSIZE:
844     /*
845      * TFTP option that specifies the block size to use for data transmission.
846      */
847     data->set.tftp_blksize = va_arg(param, long);
848     break;
849   case CURLOPT_DIRLISTONLY:
850     /*
851      * An option that changes the command to one that asks for a list
852      * only, no file info details.
853      */
854     data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
855     break;
856   case CURLOPT_APPEND:
857     /*
858      * We want to upload and append to an existing file.
859      */
860     data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
861     break;
862   case CURLOPT_FTP_FILEMETHOD:
863     /*
864      * How do access files over FTP.
865      */
866     data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
867     break;
868   case CURLOPT_NETRC:
869     /*
870      * Parse the $HOME/.netrc file
871      */
872     data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
873     break;
874   case CURLOPT_NETRC_FILE:
875     /*
876      * Use this file instead of the $HOME/.netrc file
877      */
878     result = setstropt(&data->set.str[STRING_NETRC_FILE],
879                        va_arg(param, char *));
880     break;
881   case CURLOPT_TRANSFERTEXT:
882     /*
883      * This option was previously named 'FTPASCII'. Renamed to work with
884      * more protocols than merely FTP.
885      *
886      * Transfer using ASCII (instead of BINARY).
887      */
888     data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
889     break;
890   case CURLOPT_TIMECONDITION:
891     /*
892      * Set HTTP time condition. This must be one of the defines in the
893      * curl/curl.h header file.
894      */
895     data->set.timecondition = (curl_TimeCond)va_arg(param, long);
896     break;
897   case CURLOPT_TIMEVALUE:
898     /*
899      * This is the value to compare with the remote document with the
900      * method set with CURLOPT_TIMECONDITION
901      */
902     data->set.timevalue = (time_t)va_arg(param, long);
903     break;
904   case CURLOPT_SSLVERSION:
905     /*
906      * Set explicit SSL version to try to connect with, as some SSL
907      * implementations are lame.
908      */
909 #ifdef USE_SSL
910     data->set.ssl.version = va_arg(param, long);
911 #else
912     result = CURLE_UNKNOWN_OPTION;
913 #endif
914     break;
915 
916 #ifndef CURL_DISABLE_HTTP
917   case CURLOPT_AUTOREFERER:
918     /*
919      * Switch on automatic referer that gets set if curl follows locations.
920      */
921     data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
922     break;
923 
924   case CURLOPT_ACCEPT_ENCODING:
925     /*
926      * String to use at the value of Accept-Encoding header.
927      *
928      * If the encoding is set to "" we use an Accept-Encoding header that
929      * encompasses all the encodings we support.
930      * If the encoding is set to NULL we don't send an Accept-Encoding header
931      * and ignore an received Content-Encoding header.
932      *
933      */
934     argptr = va_arg(param, char *);
935     result = setstropt(&data->set.str[STRING_ENCODING],
936                        (argptr && !*argptr)?
937                        ALL_CONTENT_ENCODINGS: argptr);
938     break;
939 
940   case CURLOPT_TRANSFER_ENCODING:
941     data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
942                                        TRUE : FALSE;
943     break;
944 
945   case CURLOPT_FOLLOWLOCATION:
946     /*
947      * Follow Location: header hints on a HTTP-server.
948      */
949     data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
950     break;
951 
952   case CURLOPT_UNRESTRICTED_AUTH:
953     /*
954      * Send authentication (user+password) when following locations, even when
955      * hostname changed.
956      */
957     data->set.http_disable_hostname_check_before_authentication =
958       (0 != va_arg(param, long)) ? TRUE : FALSE;
959     break;
960 
961   case CURLOPT_MAXREDIRS:
962     /*
963      * The maximum amount of hops you allow curl to follow Location:
964      * headers. This should mostly be used to detect never-ending loops.
965      */
966     data->set.maxredirs = va_arg(param, long);
967     break;
968 
969   case CURLOPT_POSTREDIR:
970   {
971     /*
972      * Set the behaviour of POST when redirecting
973      * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
974      * CURL_REDIR_POST_301 - POST is kept as POST after 301
975      * CURL_REDIR_POST_302 - POST is kept as POST after 302
976      * CURL_REDIR_POST_303 - POST is kept as POST after 303
977      * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
978      * other - POST is kept as POST after 301 and 302
979      */
980     int postRedir = curlx_sltosi(va_arg(param, long));
981     data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
982   }
983   break;
984 
985   case CURLOPT_POST:
986     /* Does this option serve a purpose anymore? Yes it does, when
987        CURLOPT_POSTFIELDS isn't used and the POST data is read off the
988        callback! */
989     if(va_arg(param, long)) {
990       data->set.httpreq = HTTPREQ_POST;
991       data->set.opt_no_body = FALSE; /* this is implied */
992     }
993     else
994       data->set.httpreq = HTTPREQ_GET;
995     break;
996 
997   case CURLOPT_COPYPOSTFIELDS:
998     /*
999      * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
1000      * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
1001      *  CURLOPT_COPYPOSTFIELDS and not altered later.
1002      */
1003     argptr = va_arg(param, char *);
1004 
1005     if(!argptr || data->set.postfieldsize == -1)
1006       result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
1007     else {
1008       /*
1009        *  Check that requested length does not overflow the size_t type.
1010        */
1011 
1012       if((data->set.postfieldsize < 0) ||
1013          ((sizeof(curl_off_t) != sizeof(size_t)) &&
1014           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
1015         result = CURLE_OUT_OF_MEMORY;
1016       else {
1017         char * p;
1018 
1019         (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1020 
1021         /* Allocate even when size == 0. This satisfies the need of possible
1022            later address compare to detect the COPYPOSTFIELDS mode, and
1023            to mark that postfields is used rather than read function or
1024            form data.
1025         */
1026         p = malloc((size_t)(data->set.postfieldsize?
1027                             data->set.postfieldsize:1));
1028 
1029         if(!p)
1030           result = CURLE_OUT_OF_MEMORY;
1031         else {
1032           if(data->set.postfieldsize)
1033             memcpy(p, argptr, (size_t)data->set.postfieldsize);
1034 
1035           data->set.str[STRING_COPYPOSTFIELDS] = p;
1036         }
1037       }
1038     }
1039 
1040     data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
1041     data->set.httpreq = HTTPREQ_POST;
1042     break;
1043 
1044   case CURLOPT_POSTFIELDS:
1045     /*
1046      * Like above, but use static data instead of copying it.
1047      */
1048     data->set.postfields = va_arg(param, void *);
1049     /* Release old copied data. */
1050     (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1051     data->set.httpreq = HTTPREQ_POST;
1052     break;
1053 
1054   case CURLOPT_POSTFIELDSIZE:
1055     /*
1056      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
1057      * figure it out. Enables binary posts.
1058      */
1059     bigsize = va_arg(param, long);
1060 
1061     if(data->set.postfieldsize < bigsize &&
1062        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
1063       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
1064       (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1065       data->set.postfields = NULL;
1066     }
1067 
1068     data->set.postfieldsize = bigsize;
1069     break;
1070 
1071   case CURLOPT_POSTFIELDSIZE_LARGE:
1072     /*
1073      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
1074      * figure it out. Enables binary posts.
1075      */
1076     bigsize = va_arg(param, curl_off_t);
1077 
1078     if(data->set.postfieldsize < bigsize &&
1079        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
1080       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
1081       (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
1082       data->set.postfields = NULL;
1083     }
1084 
1085     data->set.postfieldsize = bigsize;
1086     break;
1087 
1088   case CURLOPT_HTTPPOST:
1089     /*
1090      * Set to make us do HTTP POST
1091      */
1092     data->set.httppost = va_arg(param, struct curl_httppost *);
1093     data->set.httpreq = HTTPREQ_POST_FORM;
1094     data->set.opt_no_body = FALSE; /* this is implied */
1095     break;
1096 
1097   case CURLOPT_REFERER:
1098     /*
1099      * String to set in the HTTP Referer: field.
1100      */
1101     if(data->change.referer_alloc) {
1102       Curl_safefree(data->change.referer);
1103       data->change.referer_alloc = FALSE;
1104     }
1105     result = setstropt(&data->set.str[STRING_SET_REFERER],
1106                        va_arg(param, char *));
1107     data->change.referer = data->set.str[STRING_SET_REFERER];
1108     break;
1109 
1110   case CURLOPT_USERAGENT:
1111     /*
1112      * String to use in the HTTP User-Agent field
1113      */
1114     result = setstropt(&data->set.str[STRING_USERAGENT],
1115                        va_arg(param, char *));
1116     break;
1117 
1118   case CURLOPT_HTTPHEADER:
1119     /*
1120      * Set a list with HTTP headers to use (or replace internals with)
1121      */
1122     data->set.headers = va_arg(param, struct curl_slist *);
1123     break;
1124 
1125   case CURLOPT_PROXYHEADER:
1126     /*
1127      * Set a list with proxy headers to use (or replace internals with)
1128      *
1129      * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
1130      * long time we remain doing it this way until CURLOPT_PROXYHEADER is
1131      * used. As soon as this option has been used, if set to anything but
1132      * NULL, custom headers for proxies are only picked from this list.
1133      *
1134      * Set this option to NULL to restore the previous behavior.
1135      */
1136     data->set.proxyheaders = va_arg(param, struct curl_slist *);
1137     break;
1138 
1139   case CURLOPT_HEADEROPT:
1140     /*
1141      * Set header option.
1142      */
1143     arg = va_arg(param, long);
1144     data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
1145     break;
1146 
1147   case CURLOPT_HTTP200ALIASES:
1148     /*
1149      * Set a list of aliases for HTTP 200 in response header
1150      */
1151     data->set.http200aliases = va_arg(param, struct curl_slist *);
1152     break;
1153 
1154 #if !defined(CURL_DISABLE_COOKIES)
1155   case CURLOPT_COOKIE:
1156     /*
1157      * Cookie string to send to the remote server in the request.
1158      */
1159     result = setstropt(&data->set.str[STRING_COOKIE],
1160                        va_arg(param, char *));
1161     break;
1162 
1163   case CURLOPT_COOKIEFILE:
1164     /*
1165      * Set cookie file to read and parse. Can be used multiple times.
1166      */
1167     argptr = (char *)va_arg(param, void *);
1168     if(argptr) {
1169       struct curl_slist *cl;
1170       /* append the cookie file name to the list of file names, and deal with
1171          them later */
1172       cl = curl_slist_append(data->change.cookielist, argptr);
1173       if(!cl) {
1174         curl_slist_free_all(data->change.cookielist);
1175         data->change.cookielist = NULL;
1176         return CURLE_OUT_OF_MEMORY;
1177       }
1178       data->change.cookielist = cl; /* store the list for later use */
1179     }
1180     break;
1181 
1182   case CURLOPT_COOKIEJAR:
1183     /*
1184      * Set cookie file name to dump all cookies to when we're done.
1185      */
1186   {
1187     struct CookieInfo *newcookies;
1188     result = setstropt(&data->set.str[STRING_COOKIEJAR],
1189                        va_arg(param, char *));
1190 
1191     /*
1192      * Activate the cookie parser. This may or may not already
1193      * have been made.
1194      */
1195     newcookies = Curl_cookie_init(data, NULL, data->cookies,
1196                                   data->set.cookiesession);
1197     if(!newcookies)
1198       result = CURLE_OUT_OF_MEMORY;
1199     data->cookies = newcookies;
1200   }
1201     break;
1202 
1203   case CURLOPT_COOKIESESSION:
1204     /*
1205      * Set this option to TRUE to start a new "cookie session". It will
1206      * prevent the forthcoming read-cookies-from-file actions to accept
1207      * cookies that are marked as being session cookies, as they belong to a
1208      * previous session.
1209      *
1210      * In the original Netscape cookie spec, "session cookies" are cookies
1211      * with no expire date set. RFC2109 describes the same action if no
1212      * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
1213      * a 'Discard' action that can enforce the discard even for cookies that
1214      * have a Max-Age.
1215      *
1216      * We run mostly with the original cookie spec, as hardly anyone implements
1217      * anything else.
1218      */
1219     data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
1220     break;
1221 
1222   case CURLOPT_COOKIELIST:
1223     argptr = va_arg(param, char *);
1224 
1225     if(argptr == NULL)
1226       break;
1227 
1228     if(Curl_raw_equal(argptr, "ALL")) {
1229       /* clear all cookies */
1230       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1231       Curl_cookie_clearall(data->cookies);
1232       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1233     }
1234     else if(Curl_raw_equal(argptr, "SESS")) {
1235       /* clear session cookies */
1236       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1237       Curl_cookie_clearsess(data->cookies);
1238       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1239     }
1240     else if(Curl_raw_equal(argptr, "FLUSH")) {
1241       /* flush cookies to file, takes care of the locking */
1242       Curl_flush_cookies(data, 0);
1243     }
1244     else if(Curl_raw_equal(argptr, "RELOAD")) {
1245       /* reload cookies from file */
1246       Curl_cookie_loadfiles(data);
1247       break;
1248     }
1249     else {
1250       if(!data->cookies)
1251         /* if cookie engine was not running, activate it */
1252         data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
1253 
1254       argptr = strdup(argptr);
1255       if(!argptr || !data->cookies) {
1256         result = CURLE_OUT_OF_MEMORY;
1257         free(argptr);
1258       }
1259       else {
1260         Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1261 
1262         if(checkprefix("Set-Cookie:", argptr))
1263           /* HTTP Header format line */
1264           Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
1265 
1266         else
1267           /* Netscape format line */
1268           Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
1269 
1270         Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1271         free(argptr);
1272       }
1273     }
1274 
1275     break;
1276 #endif /* CURL_DISABLE_COOKIES */
1277 
1278   case CURLOPT_HTTPGET:
1279     /*
1280      * Set to force us do HTTP GET
1281      */
1282     if(va_arg(param, long)) {
1283       data->set.httpreq = HTTPREQ_GET;
1284       data->set.upload = FALSE; /* switch off upload */
1285       data->set.opt_no_body = FALSE; /* this is implied */
1286     }
1287     break;
1288 
1289   case CURLOPT_HTTP_VERSION:
1290     /*
1291      * This sets a requested HTTP version to be used. The value is one of
1292      * the listed enums in curl/curl.h.
1293      */
1294     arg = va_arg(param, long);
1295 #ifndef USE_NGHTTP2
1296     if(arg >= CURL_HTTP_VERSION_2)
1297       return CURLE_UNSUPPORTED_PROTOCOL;
1298 #endif
1299     data->set.httpversion = arg;
1300     break;
1301 
1302   case CURLOPT_HTTPAUTH:
1303     /*
1304      * Set HTTP Authentication type BITMASK.
1305      */
1306   {
1307     int bitcheck;
1308     bool authbits;
1309     unsigned long auth = va_arg(param, unsigned long);
1310 
1311     if(auth == CURLAUTH_NONE) {
1312       data->set.httpauth = auth;
1313       break;
1314     }
1315 
1316     /* the DIGEST_IE bit is only used to set a special marker, for all the
1317        rest we need to handle it as normal DIGEST */
1318     data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
1319 
1320     if(auth & CURLAUTH_DIGEST_IE) {
1321       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
1322       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
1323     }
1324 
1325     /* switch off bits we can't support */
1326 #ifndef USE_NTLM
1327     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
1328     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1329 #elif !defined(NTLM_WB_ENABLED)
1330     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1331 #endif
1332 #ifndef USE_SPNEGO
1333     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
1334                                     GSS-API or SSPI */
1335 #endif
1336 
1337     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
1338     bitcheck = 0;
1339     authbits = FALSE;
1340     while(bitcheck < 31) {
1341       if(auth & (1UL << bitcheck++)) {
1342         authbits = TRUE;
1343         break;
1344       }
1345     }
1346     if(!authbits)
1347       return CURLE_NOT_BUILT_IN; /* no supported types left! */
1348 
1349     data->set.httpauth = auth;
1350   }
1351   break;
1352 
1353   case CURLOPT_EXPECT_100_TIMEOUT_MS:
1354     /*
1355      * Time to wait for a response to a HTTP request containing an
1356      * Expect: 100-continue header before sending the data anyway.
1357      */
1358     data->set.expect_100_timeout = va_arg(param, long);
1359     break;
1360 
1361 #endif   /* CURL_DISABLE_HTTP */
1362 
1363   case CURLOPT_CUSTOMREQUEST:
1364     /*
1365      * Set a custom string to use as request
1366      */
1367     result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
1368                        va_arg(param, char *));
1369 
1370     /* we don't set
1371        data->set.httpreq = HTTPREQ_CUSTOM;
1372        here, we continue as if we were using the already set type
1373        and this just changes the actual request keyword */
1374     break;
1375 
1376 #ifndef CURL_DISABLE_PROXY
1377   case CURLOPT_HTTPPROXYTUNNEL:
1378     /*
1379      * Tunnel operations through the proxy instead of normal proxy use
1380      */
1381     data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
1382                                       TRUE : FALSE;
1383     break;
1384 
1385   case CURLOPT_PROXYPORT:
1386     /*
1387      * Explicitly set HTTP proxy port number.
1388      */
1389     data->set.proxyport = va_arg(param, long);
1390     break;
1391 
1392   case CURLOPT_PROXYAUTH:
1393     /*
1394      * Set HTTP Authentication type BITMASK.
1395      */
1396   {
1397     int bitcheck;
1398     bool authbits;
1399     unsigned long auth = va_arg(param, unsigned long);
1400 
1401     if(auth == CURLAUTH_NONE) {
1402       data->set.proxyauth = auth;
1403       break;
1404     }
1405 
1406     /* the DIGEST_IE bit is only used to set a special marker, for all the
1407        rest we need to handle it as normal DIGEST */
1408     data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
1409 
1410     if(auth & CURLAUTH_DIGEST_IE) {
1411       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
1412       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
1413     }
1414     /* switch off bits we can't support */
1415 #ifndef USE_NTLM
1416     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
1417     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1418 #elif !defined(NTLM_WB_ENABLED)
1419     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
1420 #endif
1421 #ifndef USE_SPNEGO
1422     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
1423                                     GSS-API or SSPI */
1424 #endif
1425 
1426     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
1427     bitcheck = 0;
1428     authbits = FALSE;
1429     while(bitcheck < 31) {
1430       if(auth & (1UL << bitcheck++)) {
1431         authbits = TRUE;
1432         break;
1433       }
1434     }
1435     if(!authbits)
1436       return CURLE_NOT_BUILT_IN; /* no supported types left! */
1437 
1438     data->set.proxyauth = auth;
1439   }
1440   break;
1441 
1442   case CURLOPT_PROXY:
1443     /*
1444      * Set proxy server:port to use as HTTP proxy.
1445      *
1446      * If the proxy is set to "" we explicitly say that we don't want to use a
1447      * proxy (even though there might be environment variables saying so).
1448      *
1449      * Setting it to NULL, means no proxy but allows the environment variables
1450      * to decide for us.
1451      */
1452     result = setstropt(&data->set.str[STRING_PROXY],
1453                        va_arg(param, char *));
1454     break;
1455 
1456   case CURLOPT_PROXYTYPE:
1457     /*
1458      * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
1459      */
1460     data->set.proxytype = (curl_proxytype)va_arg(param, long);
1461     break;
1462 
1463   case CURLOPT_PROXY_TRANSFER_MODE:
1464     /*
1465      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
1466      */
1467     switch (va_arg(param, long)) {
1468     case 0:
1469       data->set.proxy_transfer_mode = FALSE;
1470       break;
1471     case 1:
1472       data->set.proxy_transfer_mode = TRUE;
1473       break;
1474     default:
1475       /* reserve other values for future use */
1476       result = CURLE_UNKNOWN_OPTION;
1477       break;
1478     }
1479     break;
1480 #endif   /* CURL_DISABLE_PROXY */
1481 
1482 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
1483   case CURLOPT_SOCKS5_GSSAPI_NEC:
1484     /*
1485      * Set flag for NEC SOCK5 support
1486      */
1487     data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
1488     break;
1489 
1490   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
1491   case CURLOPT_PROXY_SERVICE_NAME:
1492     /*
1493      * Set proxy authentication service name for Kerberos 5 and SPNEGO
1494      */
1495     result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
1496                        va_arg(param, char *));
1497     break;
1498 #endif
1499 
1500 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
1501     defined(USE_SPNEGO)
1502   case CURLOPT_SERVICE_NAME:
1503     /*
1504      * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
1505      */
1506     result = setstropt(&data->set.str[STRING_SERVICE_NAME],
1507                        va_arg(param, char *));
1508     break;
1509 
1510 #endif
1511 
1512   case CURLOPT_HEADERDATA:
1513     /*
1514      * Custom pointer to pass the header write callback function
1515      */
1516     data->set.writeheader = (void *)va_arg(param, void *);
1517     break;
1518   case CURLOPT_ERRORBUFFER:
1519     /*
1520      * Error buffer provided by the caller to get the human readable
1521      * error string in.
1522      */
1523     data->set.errorbuffer = va_arg(param, char *);
1524     break;
1525   case CURLOPT_WRITEDATA:
1526     /*
1527      * FILE pointer to write to. Or possibly
1528      * used as argument to the write callback.
1529      */
1530     data->set.out = va_arg(param, void *);
1531     break;
1532   case CURLOPT_FTPPORT:
1533     /*
1534      * Use FTP PORT, this also specifies which IP address to use
1535      */
1536     result = setstropt(&data->set.str[STRING_FTPPORT],
1537                        va_arg(param, char *));
1538     data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
1539     break;
1540 
1541   case CURLOPT_FTP_USE_EPRT:
1542     data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
1543     break;
1544 
1545   case CURLOPT_FTP_USE_EPSV:
1546     data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
1547     break;
1548 
1549   case CURLOPT_FTP_USE_PRET:
1550     data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
1551     break;
1552 
1553   case CURLOPT_FTP_SSL_CCC:
1554     data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
1555     break;
1556 
1557   case CURLOPT_FTP_SKIP_PASV_IP:
1558     /*
1559      * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
1560      * bypass of the IP address in PASV responses.
1561      */
1562     data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
1563     break;
1564 
1565   case CURLOPT_READDATA:
1566     /*
1567      * FILE pointer to read the file to be uploaded from. Or possibly
1568      * used as argument to the read callback.
1569      */
1570     data->set.in_set = va_arg(param, void *);
1571     break;
1572   case CURLOPT_INFILESIZE:
1573     /*
1574      * If known, this should inform curl about the file size of the
1575      * to-be-uploaded file.
1576      */
1577     data->set.filesize = va_arg(param, long);
1578     break;
1579   case CURLOPT_INFILESIZE_LARGE:
1580     /*
1581      * If known, this should inform curl about the file size of the
1582      * to-be-uploaded file.
1583      */
1584     data->set.filesize = va_arg(param, curl_off_t);
1585     break;
1586   case CURLOPT_LOW_SPEED_LIMIT:
1587     /*
1588      * The low speed limit that if transfers are below this for
1589      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
1590      */
1591     data->set.low_speed_limit=va_arg(param, long);
1592     break;
1593   case CURLOPT_MAX_SEND_SPEED_LARGE:
1594     /*
1595      * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
1596      * bytes per second the transfer is throttled..
1597      */
1598     data->set.max_send_speed=va_arg(param, curl_off_t);
1599     break;
1600   case CURLOPT_MAX_RECV_SPEED_LARGE:
1601     /*
1602      * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
1603      * second the transfer is throttled..
1604      */
1605     data->set.max_recv_speed=va_arg(param, curl_off_t);
1606     break;
1607   case CURLOPT_LOW_SPEED_TIME:
1608     /*
1609      * The low speed time that if transfers are below the set
1610      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
1611      */
1612     data->set.low_speed_time=va_arg(param, long);
1613     break;
1614   case CURLOPT_URL:
1615     /*
1616      * The URL to fetch.
1617      */
1618     if(data->change.url_alloc) {
1619       /* the already set URL is allocated, free it first! */
1620       Curl_safefree(data->change.url);
1621       data->change.url_alloc = FALSE;
1622     }
1623     result = setstropt(&data->set.str[STRING_SET_URL],
1624                        va_arg(param, char *));
1625     data->change.url = data->set.str[STRING_SET_URL];
1626     break;
1627   case CURLOPT_PORT:
1628     /*
1629      * The port number to use when getting the URL
1630      */
1631     data->set.use_port = va_arg(param, long);
1632     break;
1633   case CURLOPT_TIMEOUT:
1634     /*
1635      * The maximum time you allow curl to use for a single transfer
1636      * operation.
1637      */
1638     data->set.timeout = va_arg(param, long) * 1000L;
1639     break;
1640 
1641   case CURLOPT_TIMEOUT_MS:
1642     data->set.timeout = va_arg(param, long);
1643     break;
1644 
1645   case CURLOPT_CONNECTTIMEOUT:
1646     /*
1647      * The maximum time you allow curl to use to connect.
1648      */
1649     data->set.connecttimeout = va_arg(param, long) * 1000L;
1650     break;
1651 
1652   case CURLOPT_CONNECTTIMEOUT_MS:
1653     data->set.connecttimeout = va_arg(param, long);
1654     break;
1655 
1656   case CURLOPT_ACCEPTTIMEOUT_MS:
1657     /*
1658      * The maximum time you allow curl to wait for server connect
1659      */
1660     data->set.accepttimeout = va_arg(param, long);
1661     break;
1662 
1663   case CURLOPT_USERPWD:
1664     /*
1665      * user:password to use in the operation
1666      */
1667     result = setstropt_userpwd(va_arg(param, char *),
1668                                &data->set.str[STRING_USERNAME],
1669                                &data->set.str[STRING_PASSWORD]);
1670     break;
1671 
1672   case CURLOPT_USERNAME:
1673     /*
1674      * authentication user name to use in the operation
1675      */
1676     result = setstropt(&data->set.str[STRING_USERNAME],
1677                        va_arg(param, char *));
1678     break;
1679 
1680   case CURLOPT_PASSWORD:
1681     /*
1682      * authentication password to use in the operation
1683      */
1684     result = setstropt(&data->set.str[STRING_PASSWORD],
1685                        va_arg(param, char *));
1686     break;
1687 
1688   case CURLOPT_LOGIN_OPTIONS:
1689     /*
1690      * authentication options to use in the operation
1691      */
1692     result = setstropt(&data->set.str[STRING_OPTIONS],
1693                        va_arg(param, char *));
1694     break;
1695 
1696   case CURLOPT_XOAUTH2_BEARER:
1697     /*
1698      * OAuth 2.0 bearer token to use in the operation
1699      */
1700     result = setstropt(&data->set.str[STRING_BEARER],
1701                        va_arg(param, char *));
1702     break;
1703 
1704   case CURLOPT_POSTQUOTE:
1705     /*
1706      * List of RAW FTP commands to use after a transfer
1707      */
1708     data->set.postquote = va_arg(param, struct curl_slist *);
1709     break;
1710   case CURLOPT_PREQUOTE:
1711     /*
1712      * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
1713      */
1714     data->set.prequote = va_arg(param, struct curl_slist *);
1715     break;
1716   case CURLOPT_QUOTE:
1717     /*
1718      * List of RAW FTP commands to use before a transfer
1719      */
1720     data->set.quote = va_arg(param, struct curl_slist *);
1721     break;
1722   case CURLOPT_RESOLVE:
1723     /*
1724      * List of NAME:[address] names to populate the DNS cache with
1725      * Prefix the NAME with dash (-) to _remove_ the name from the cache.
1726      *
1727      * Names added with this API will remain in the cache until explicitly
1728      * removed or the handle is cleaned up.
1729      *
1730      * This API can remove any name from the DNS cache, but only entries
1731      * that aren't actually in use right now will be pruned immediately.
1732      */
1733     data->set.resolve = va_arg(param, struct curl_slist *);
1734     data->change.resolve = data->set.resolve;
1735     break;
1736   case CURLOPT_PROGRESSFUNCTION:
1737     /*
1738      * Progress callback function
1739      */
1740     data->set.fprogress = va_arg(param, curl_progress_callback);
1741     if(data->set.fprogress)
1742       data->progress.callback = TRUE; /* no longer internal */
1743     else
1744       data->progress.callback = FALSE; /* NULL enforces internal */
1745     break;
1746 
1747   case CURLOPT_XFERINFOFUNCTION:
1748     /*
1749      * Transfer info callback function
1750      */
1751     data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
1752     if(data->set.fxferinfo)
1753       data->progress.callback = TRUE; /* no longer internal */
1754     else
1755       data->progress.callback = FALSE; /* NULL enforces internal */
1756 
1757     break;
1758 
1759   case CURLOPT_PROGRESSDATA:
1760     /*
1761      * Custom client data to pass to the progress callback
1762      */
1763     data->set.progress_client = va_arg(param, void *);
1764     break;
1765 
1766 #ifndef CURL_DISABLE_PROXY
1767   case CURLOPT_PROXYUSERPWD:
1768     /*
1769      * user:password needed to use the proxy
1770      */
1771     result = setstropt_userpwd(va_arg(param, char *),
1772                                &data->set.str[STRING_PROXYUSERNAME],
1773                                &data->set.str[STRING_PROXYPASSWORD]);
1774     break;
1775   case CURLOPT_PROXYUSERNAME:
1776     /*
1777      * authentication user name to use in the operation
1778      */
1779     result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
1780                        va_arg(param, char *));
1781     break;
1782   case CURLOPT_PROXYPASSWORD:
1783     /*
1784      * authentication password to use in the operation
1785      */
1786     result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
1787                        va_arg(param, char *));
1788     break;
1789   case CURLOPT_NOPROXY:
1790     /*
1791      * proxy exception list
1792      */
1793     result = setstropt(&data->set.str[STRING_NOPROXY],
1794                        va_arg(param, char *));
1795     break;
1796 #endif
1797 
1798   case CURLOPT_RANGE:
1799     /*
1800      * What range of the file you want to transfer
1801      */
1802     result = setstropt(&data->set.str[STRING_SET_RANGE],
1803                        va_arg(param, char *));
1804     break;
1805   case CURLOPT_RESUME_FROM:
1806     /*
1807      * Resume transfer at the give file position
1808      */
1809     data->set.set_resume_from = va_arg(param, long);
1810     break;
1811   case CURLOPT_RESUME_FROM_LARGE:
1812     /*
1813      * Resume transfer at the give file position
1814      */
1815     data->set.set_resume_from = va_arg(param, curl_off_t);
1816     break;
1817   case CURLOPT_DEBUGFUNCTION:
1818     /*
1819      * stderr write callback.
1820      */
1821     data->set.fdebug = va_arg(param, curl_debug_callback);
1822     /*
1823      * if the callback provided is NULL, it'll use the default callback
1824      */
1825     break;
1826   case CURLOPT_DEBUGDATA:
1827     /*
1828      * Set to a void * that should receive all error writes. This
1829      * defaults to CURLOPT_STDERR for normal operations.
1830      */
1831     data->set.debugdata = va_arg(param, void *);
1832     break;
1833   case CURLOPT_STDERR:
1834     /*
1835      * Set to a FILE * that should receive all error writes. This
1836      * defaults to stderr for normal operations.
1837      */
1838     data->set.err = va_arg(param, FILE *);
1839     if(!data->set.err)
1840       data->set.err = stderr;
1841     break;
1842   case CURLOPT_HEADERFUNCTION:
1843     /*
1844      * Set header write callback
1845      */
1846     data->set.fwrite_header = va_arg(param, curl_write_callback);
1847     break;
1848   case CURLOPT_WRITEFUNCTION:
1849     /*
1850      * Set data write callback
1851      */
1852     data->set.fwrite_func = va_arg(param, curl_write_callback);
1853     if(!data->set.fwrite_func) {
1854       data->set.is_fwrite_set = 0;
1855       /* When set to NULL, reset to our internal default function */
1856       data->set.fwrite_func = (curl_write_callback)fwrite;
1857     }
1858     else
1859       data->set.is_fwrite_set = 1;
1860     break;
1861   case CURLOPT_READFUNCTION:
1862     /*
1863      * Read data callback
1864      */
1865     data->set.fread_func_set = va_arg(param, curl_read_callback);
1866     if(!data->set.fread_func_set) {
1867       data->set.is_fread_set = 0;
1868       /* When set to NULL, reset to our internal default function */
1869       data->set.fread_func_set = (curl_read_callback)fread;
1870     }
1871     else
1872       data->set.is_fread_set = 1;
1873     break;
1874   case CURLOPT_SEEKFUNCTION:
1875     /*
1876      * Seek callback. Might be NULL.
1877      */
1878     data->set.seek_func = va_arg(param, curl_seek_callback);
1879     break;
1880   case CURLOPT_SEEKDATA:
1881     /*
1882      * Seek control callback. Might be NULL.
1883      */
1884     data->set.seek_client = va_arg(param, void *);
1885     break;
1886   case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
1887     /*
1888      * "Convert from network encoding" callback
1889      */
1890     data->set.convfromnetwork = va_arg(param, curl_conv_callback);
1891     break;
1892   case CURLOPT_CONV_TO_NETWORK_FUNCTION:
1893     /*
1894      * "Convert to network encoding" callback
1895      */
1896     data->set.convtonetwork = va_arg(param, curl_conv_callback);
1897     break;
1898   case CURLOPT_CONV_FROM_UTF8_FUNCTION:
1899     /*
1900      * "Convert from UTF-8 encoding" callback
1901      */
1902     data->set.convfromutf8 = va_arg(param, curl_conv_callback);
1903     break;
1904   case CURLOPT_IOCTLFUNCTION:
1905     /*
1906      * I/O control callback. Might be NULL.
1907      */
1908     data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
1909     break;
1910   case CURLOPT_IOCTLDATA:
1911     /*
1912      * I/O control data pointer. Might be NULL.
1913      */
1914     data->set.ioctl_client = va_arg(param, void *);
1915     break;
1916   case CURLOPT_SSLCERT:
1917     /*
1918      * String that holds file name of the SSL certificate to use
1919      */
1920     result = setstropt(&data->set.str[STRING_CERT],
1921                        va_arg(param, char *));
1922     break;
1923   case CURLOPT_SSLCERTTYPE:
1924     /*
1925      * String that holds file type of the SSL certificate to use
1926      */
1927     result = setstropt(&data->set.str[STRING_CERT_TYPE],
1928                        va_arg(param, char *));
1929     break;
1930   case CURLOPT_SSLKEY:
1931     /*
1932      * String that holds file name of the SSL key to use
1933      */
1934     result = setstropt(&data->set.str[STRING_KEY],
1935                        va_arg(param, char *));
1936     break;
1937   case CURLOPT_SSLKEYTYPE:
1938     /*
1939      * String that holds file type of the SSL key to use
1940      */
1941     result = setstropt(&data->set.str[STRING_KEY_TYPE],
1942                        va_arg(param, char *));
1943     break;
1944   case CURLOPT_KEYPASSWD:
1945     /*
1946      * String that holds the SSL or SSH private key password.
1947      */
1948     result = setstropt(&data->set.str[STRING_KEY_PASSWD],
1949                        va_arg(param, char *));
1950     break;
1951   case CURLOPT_SSLENGINE:
1952     /*
1953      * String that holds the SSL crypto engine.
1954      */
1955     argptr = va_arg(param, char *);
1956     if(argptr && argptr[0])
1957       result = Curl_ssl_set_engine(data, argptr);
1958     break;
1959 
1960   case CURLOPT_SSLENGINE_DEFAULT:
1961     /*
1962      * flag to set engine as default.
1963      */
1964     result = Curl_ssl_set_engine_default(data);
1965     break;
1966   case CURLOPT_CRLF:
1967     /*
1968      * Kludgy option to enable CRLF conversions. Subject for removal.
1969      */
1970     data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
1971     break;
1972 
1973   case CURLOPT_INTERFACE:
1974     /*
1975      * Set what interface or address/hostname to bind the socket to when
1976      * performing an operation and thus what from-IP your connection will use.
1977      */
1978     result = setstropt(&data->set.str[STRING_DEVICE],
1979                        va_arg(param, char *));
1980     break;
1981   case CURLOPT_LOCALPORT:
1982     /*
1983      * Set what local port to bind the socket to when performing an operation.
1984      */
1985     data->set.localport = curlx_sltous(va_arg(param, long));
1986     break;
1987   case CURLOPT_LOCALPORTRANGE:
1988     /*
1989      * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
1990      */
1991     data->set.localportrange = curlx_sltosi(va_arg(param, long));
1992     break;
1993   case CURLOPT_KRBLEVEL:
1994     /*
1995      * A string that defines the kerberos security level.
1996      */
1997     result = setstropt(&data->set.str[STRING_KRB_LEVEL],
1998                        va_arg(param, char *));
1999     data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
2000     break;
2001   case CURLOPT_GSSAPI_DELEGATION:
2002     /*
2003      * GSS-API credential delegation
2004      */
2005     data->set.gssapi_delegation = va_arg(param, long);
2006     break;
2007   case CURLOPT_SSL_VERIFYPEER:
2008     /*
2009      * Enable peer SSL verifying.
2010      */
2011     data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
2012     break;
2013   case CURLOPT_SSL_VERIFYHOST:
2014     /*
2015      * Enable verification of the host name in the peer certificate
2016      */
2017     arg = va_arg(param, long);
2018 
2019     /* Obviously people are not reading documentation and too many thought
2020        this argument took a boolean when it wasn't and misused it. We thus ban
2021        1 as a sensible input and we warn about its use. Then we only have the
2022        2 action internally stored as TRUE. */
2023 
2024     if(1 == arg) {
2025       failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
2026       return CURLE_BAD_FUNCTION_ARGUMENT;
2027     }
2028 
2029     data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
2030     break;
2031   case CURLOPT_SSL_VERIFYSTATUS:
2032     /*
2033      * Enable certificate status verifying.
2034      */
2035     if(!Curl_ssl_cert_status_request()) {
2036       result = CURLE_NOT_BUILT_IN;
2037       break;
2038     }
2039 
2040     data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
2041     break;
2042   case CURLOPT_SSL_CTX_FUNCTION:
2043 #ifdef have_curlssl_ssl_ctx
2044     /*
2045      * Set a SSL_CTX callback
2046      */
2047     data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
2048 #else
2049     result = CURLE_NOT_BUILT_IN;
2050 #endif
2051     break;
2052   case CURLOPT_SSL_CTX_DATA:
2053 #ifdef have_curlssl_ssl_ctx
2054     /*
2055      * Set a SSL_CTX callback parameter pointer
2056      */
2057     data->set.ssl.fsslctxp = va_arg(param, void *);
2058 #else
2059     result = CURLE_NOT_BUILT_IN;
2060 #endif
2061     break;
2062   case CURLOPT_SSL_FALSESTART:
2063     /*
2064      * Enable TLS false start.
2065      */
2066     if(!Curl_ssl_false_start()) {
2067       result = CURLE_NOT_BUILT_IN;
2068       break;
2069     }
2070 
2071     data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
2072     break;
2073   case CURLOPT_CERTINFO:
2074 #ifdef have_curlssl_certinfo
2075     data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
2076 #else
2077     result = CURLE_NOT_BUILT_IN;
2078 #endif
2079     break;
2080   case CURLOPT_PINNEDPUBLICKEY:
2081 #ifdef have_curlssl_pinnedpubkey /* only by supported backends */
2082     /*
2083      * Set pinned public key for SSL connection.
2084      * Specify file name of the public key in DER format.
2085      */
2086     result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
2087                        va_arg(param, char *));
2088 #else
2089     result = CURLE_NOT_BUILT_IN;
2090 #endif
2091     break;
2092   case CURLOPT_CAINFO:
2093     /*
2094      * Set CA info for SSL connection. Specify file name of the CA certificate
2095      */
2096     result = setstropt(&data->set.str[STRING_SSL_CAFILE],
2097                        va_arg(param, char *));
2098     break;
2099   case CURLOPT_CAPATH:
2100 #ifdef have_curlssl_ca_path /* not supported by all backends */
2101     /*
2102      * Set CA path info for SSL connection. Specify directory name of the CA
2103      * certificates which have been prepared using openssl c_rehash utility.
2104      */
2105     /* This does not work on windows. */
2106     result = setstropt(&data->set.str[STRING_SSL_CAPATH],
2107                        va_arg(param, char *));
2108 #else
2109     result = CURLE_NOT_BUILT_IN;
2110 #endif
2111     break;
2112   case CURLOPT_CRLFILE:
2113     /*
2114      * Set CRL file info for SSL connection. Specify file name of the CRL
2115      * to check certificates revocation
2116      */
2117     result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
2118                        va_arg(param, char *));
2119     break;
2120   case CURLOPT_ISSUERCERT:
2121     /*
2122      * Set Issuer certificate file
2123      * to check certificates issuer
2124      */
2125     result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
2126                        va_arg(param, char *));
2127     break;
2128   case CURLOPT_TELNETOPTIONS:
2129     /*
2130      * Set a linked list of telnet options
2131      */
2132     data->set.telnet_options = va_arg(param, struct curl_slist *);
2133     break;
2134 
2135   case CURLOPT_BUFFERSIZE:
2136     /*
2137      * The application kindly asks for a differently sized receive buffer.
2138      * If it seems reasonable, we'll use it.
2139      */
2140     data->set.buffer_size = va_arg(param, long);
2141 
2142     if((data->set.buffer_size> (BUFSIZE -1)) ||
2143        (data->set.buffer_size < 1))
2144       data->set.buffer_size = 0; /* huge internal default */
2145 
2146     break;
2147 
2148   case CURLOPT_NOSIGNAL:
2149     /*
2150      * The application asks not to set any signal() or alarm() handlers,
2151      * even when using a timeout.
2152      */
2153     data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
2154     break;
2155 
2156   case CURLOPT_SHARE:
2157   {
2158     struct Curl_share *set;
2159     set = va_arg(param, struct Curl_share *);
2160 
2161     /* disconnect from old share, if any */
2162     if(data->share) {
2163       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
2164 
2165       if(data->dns.hostcachetype == HCACHE_SHARED) {
2166         data->dns.hostcache = NULL;
2167         data->dns.hostcachetype = HCACHE_NONE;
2168       }
2169 
2170 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
2171       if(data->share->cookies == data->cookies)
2172         data->cookies = NULL;
2173 #endif
2174 
2175       if(data->share->sslsession == data->state.session)
2176         data->state.session = NULL;
2177 
2178       data->share->dirty--;
2179 
2180       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
2181       data->share = NULL;
2182     }
2183 
2184     /* use new share if it set */
2185     data->share = set;
2186     if(data->share) {
2187 
2188       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
2189 
2190       data->share->dirty++;
2191 
2192       if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
2193         /* use shared host cache */
2194         data->dns.hostcache = &data->share->hostcache;
2195         data->dns.hostcachetype = HCACHE_SHARED;
2196       }
2197 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
2198       if(data->share->cookies) {
2199         /* use shared cookie list, first free own one if any */
2200         Curl_cookie_cleanup(data->cookies);
2201         /* enable cookies since we now use a share that uses cookies! */
2202         data->cookies = data->share->cookies;
2203       }
2204 #endif   /* CURL_DISABLE_HTTP */
2205       if(data->share->sslsession) {
2206         data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
2207         data->state.session = data->share->sslsession;
2208       }
2209       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
2210 
2211     }
2212     /* check for host cache not needed,
2213      * it will be done by curl_easy_perform */
2214   }
2215   break;
2216 
2217   case CURLOPT_PRIVATE:
2218     /*
2219      * Set private data pointer.
2220      */
2221     data->set.private_data = va_arg(param, void *);
2222     break;
2223 
2224   case CURLOPT_MAXFILESIZE:
2225     /*
2226      * Set the maximum size of a file to download.
2227      */
2228     data->set.max_filesize = va_arg(param, long);
2229     break;
2230 
2231 #ifdef USE_SSL
2232   case CURLOPT_USE_SSL:
2233     /*
2234      * Make transfers attempt to use SSL/TLS.
2235      */
2236     data->set.use_ssl = (curl_usessl)va_arg(param, long);
2237     break;
2238 
2239   case CURLOPT_SSL_OPTIONS:
2240     arg = va_arg(param, long);
2241     data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
2242     data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2243     break;
2244 
2245 #endif
2246   case CURLOPT_FTPSSLAUTH:
2247     /*
2248      * Set a specific auth for FTP-SSL transfers.
2249      */
2250     data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
2251     break;
2252 
2253   case CURLOPT_IPRESOLVE:
2254     data->set.ipver = va_arg(param, long);
2255     break;
2256 
2257   case CURLOPT_MAXFILESIZE_LARGE:
2258     /*
2259      * Set the maximum size of a file to download.
2260      */
2261     data->set.max_filesize = va_arg(param, curl_off_t);
2262     break;
2263 
2264   case CURLOPT_TCP_NODELAY:
2265     /*
2266      * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
2267      * algorithm
2268      */
2269     data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
2270     break;
2271 
2272   case CURLOPT_FTP_ACCOUNT:
2273     result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
2274                        va_arg(param, char *));
2275     break;
2276 
2277   case CURLOPT_IGNORE_CONTENT_LENGTH:
2278     data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
2279     break;
2280 
2281   case CURLOPT_CONNECT_ONLY:
2282     /*
2283      * No data transfer, set up connection and let application use the socket
2284      */
2285     data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
2286     break;
2287 
2288   case CURLOPT_FTP_ALTERNATIVE_TO_USER:
2289     result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
2290                        va_arg(param, char *));
2291     break;
2292 
2293   case CURLOPT_SOCKOPTFUNCTION:
2294     /*
2295      * socket callback function: called after socket() but before connect()
2296      */
2297     data->set.fsockopt = va_arg(param, curl_sockopt_callback);
2298     break;
2299 
2300   case CURLOPT_SOCKOPTDATA:
2301     /*
2302      * socket callback data pointer. Might be NULL.
2303      */
2304     data->set.sockopt_client = va_arg(param, void *);
2305     break;
2306 
2307   case CURLOPT_OPENSOCKETFUNCTION:
2308     /*
2309      * open/create socket callback function: called instead of socket(),
2310      * before connect()
2311      */
2312     data->set.fopensocket = va_arg(param, curl_opensocket_callback);
2313     break;
2314 
2315   case CURLOPT_OPENSOCKETDATA:
2316     /*
2317      * socket callback data pointer. Might be NULL.
2318      */
2319     data->set.opensocket_client = va_arg(param, void *);
2320     break;
2321 
2322   case CURLOPT_CLOSESOCKETFUNCTION:
2323     /*
2324      * close socket callback function: called instead of close()
2325      * when shutting down a connection
2326      */
2327     data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
2328     break;
2329 
2330   case CURLOPT_CLOSESOCKETDATA:
2331     /*
2332      * socket callback data pointer. Might be NULL.
2333      */
2334     data->set.closesocket_client = va_arg(param, void *);
2335     break;
2336 
2337   case CURLOPT_SSL_SESSIONID_CACHE:
2338     data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
2339     break;
2340 
2341 #ifdef USE_LIBSSH2
2342     /* we only include SSH options if explicitly built to support SSH */
2343   case CURLOPT_SSH_AUTH_TYPES:
2344     data->set.ssh_auth_types = va_arg(param, long);
2345     break;
2346 
2347   case CURLOPT_SSH_PUBLIC_KEYFILE:
2348     /*
2349      * Use this file instead of the $HOME/.ssh/id_dsa.pub file
2350      */
2351     result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
2352                        va_arg(param, char *));
2353     break;
2354 
2355   case CURLOPT_SSH_PRIVATE_KEYFILE:
2356     /*
2357      * Use this file instead of the $HOME/.ssh/id_dsa file
2358      */
2359     result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
2360                        va_arg(param, char *));
2361     break;
2362   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2363     /*
2364      * Option to allow for the MD5 of the host public key to be checked
2365      * for validation purposes.
2366      */
2367     result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
2368                        va_arg(param, char *));
2369     break;
2370 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
2371   case CURLOPT_SSH_KNOWNHOSTS:
2372     /*
2373      * Store the file name to read known hosts from.
2374      */
2375     result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
2376                        va_arg(param, char *));
2377     break;
2378 
2379   case CURLOPT_SSH_KEYFUNCTION:
2380     /* setting to NULL is fine since the ssh.c functions themselves will
2381        then rever to use the internal default */
2382     data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
2383     break;
2384 
2385   case CURLOPT_SSH_KEYDATA:
2386     /*
2387      * Custom client data to pass to the SSH keyfunc callback
2388      */
2389     data->set.ssh_keyfunc_userp = va_arg(param, void *);
2390     break;
2391 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
2392 
2393 #endif /* USE_LIBSSH2 */
2394 
2395   case CURLOPT_HTTP_TRANSFER_DECODING:
2396     /*
2397      * disable libcurl transfer encoding is used
2398      */
2399     data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2400     break;
2401 
2402   case CURLOPT_HTTP_CONTENT_DECODING:
2403     /*
2404      * raw data passed to the application when content encoding is used
2405      */
2406     data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2407     break;
2408 
2409   case CURLOPT_NEW_FILE_PERMS:
2410     /*
2411      * Uses these permissions instead of 0644
2412      */
2413     data->set.new_file_perms = va_arg(param, long);
2414     break;
2415 
2416   case CURLOPT_NEW_DIRECTORY_PERMS:
2417     /*
2418      * Uses these permissions instead of 0755
2419      */
2420     data->set.new_directory_perms = va_arg(param, long);
2421     break;
2422 
2423   case CURLOPT_ADDRESS_SCOPE:
2424     /*
2425      * We always get longs when passed plain numericals, but for this value we
2426      * know that an unsigned int will always hold the value so we blindly
2427      * typecast to this type
2428      */
2429     data->set.scope_id = curlx_sltoui(va_arg(param, long));
2430     break;
2431 
2432   case CURLOPT_PROTOCOLS:
2433     /* set the bitmask for the protocols that are allowed to be used for the
2434        transfer, which thus helps the app which takes URLs from users or other
2435        external inputs and want to restrict what protocol(s) to deal
2436        with. Defaults to CURLPROTO_ALL. */
2437     data->set.allowed_protocols = va_arg(param, long);
2438     break;
2439 
2440   case CURLOPT_REDIR_PROTOCOLS:
2441     /* set the bitmask for the protocols that libcurl is allowed to follow to,
2442        as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
2443        to be set in both bitmasks to be allowed to get redirected to. Defaults
2444        to all protocols except FILE and SCP. */
2445     data->set.redir_protocols = va_arg(param, long);
2446     break;
2447 
2448   case CURLOPT_DEFAULT_PROTOCOL:
2449     /* Set the protocol to use when the URL doesn't include any protocol */
2450     result = setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
2451                        va_arg(param, char *));
2452     break;
2453 
2454   case CURLOPT_MAIL_FROM:
2455     /* Set the SMTP mail originator */
2456     result = setstropt(&data->set.str[STRING_MAIL_FROM],
2457                        va_arg(param, char *));
2458     break;
2459 
2460   case CURLOPT_MAIL_AUTH:
2461     /* Set the SMTP auth originator */
2462     result = setstropt(&data->set.str[STRING_MAIL_AUTH],
2463                        va_arg(param, char *));
2464     break;
2465 
2466   case CURLOPT_MAIL_RCPT:
2467     /* Set the list of mail recipients */
2468     data->set.mail_rcpt = va_arg(param, struct curl_slist *);
2469     break;
2470 
2471   case CURLOPT_SASL_IR:
2472     /* Enable/disable SASL initial response */
2473     data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
2474     break;
2475 
2476   case CURLOPT_RTSP_REQUEST:
2477     {
2478       /*
2479        * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
2480        * Would this be better if the RTSPREQ_* were just moved into here?
2481        */
2482       long curl_rtspreq = va_arg(param, long);
2483       Curl_RtspReq rtspreq = RTSPREQ_NONE;
2484       switch(curl_rtspreq) {
2485         case CURL_RTSPREQ_OPTIONS:
2486           rtspreq = RTSPREQ_OPTIONS;
2487           break;
2488 
2489         case CURL_RTSPREQ_DESCRIBE:
2490           rtspreq = RTSPREQ_DESCRIBE;
2491           break;
2492 
2493         case CURL_RTSPREQ_ANNOUNCE:
2494           rtspreq = RTSPREQ_ANNOUNCE;
2495           break;
2496 
2497         case CURL_RTSPREQ_SETUP:
2498           rtspreq = RTSPREQ_SETUP;
2499           break;
2500 
2501         case CURL_RTSPREQ_PLAY:
2502           rtspreq = RTSPREQ_PLAY;
2503           break;
2504 
2505         case CURL_RTSPREQ_PAUSE:
2506           rtspreq = RTSPREQ_PAUSE;
2507           break;
2508 
2509         case CURL_RTSPREQ_TEARDOWN:
2510           rtspreq = RTSPREQ_TEARDOWN;
2511           break;
2512 
2513         case CURL_RTSPREQ_GET_PARAMETER:
2514           rtspreq = RTSPREQ_GET_PARAMETER;
2515           break;
2516 
2517         case CURL_RTSPREQ_SET_PARAMETER:
2518           rtspreq = RTSPREQ_SET_PARAMETER;
2519           break;
2520 
2521         case CURL_RTSPREQ_RECORD:
2522           rtspreq = RTSPREQ_RECORD;
2523           break;
2524 
2525         case CURL_RTSPREQ_RECEIVE:
2526           rtspreq = RTSPREQ_RECEIVE;
2527           break;
2528         default:
2529           rtspreq = RTSPREQ_NONE;
2530       }
2531 
2532       data->set.rtspreq = rtspreq;
2533     break;
2534     }
2535 
2536 
2537   case CURLOPT_RTSP_SESSION_ID:
2538     /*
2539      * Set the RTSP Session ID manually. Useful if the application is
2540      * resuming a previously established RTSP session
2541      */
2542     result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
2543                        va_arg(param, char *));
2544     break;
2545 
2546   case CURLOPT_RTSP_STREAM_URI:
2547     /*
2548      * Set the Stream URI for the RTSP request. Unless the request is
2549      * for generic server options, the application will need to set this.
2550      */
2551     result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
2552                        va_arg(param, char *));
2553     break;
2554 
2555   case CURLOPT_RTSP_TRANSPORT:
2556     /*
2557      * The content of the Transport: header for the RTSP request
2558      */
2559     result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
2560                        va_arg(param, char *));
2561     break;
2562 
2563   case CURLOPT_RTSP_CLIENT_CSEQ:
2564     /*
2565      * Set the CSEQ number to issue for the next RTSP request. Useful if the
2566      * application is resuming a previously broken connection. The CSEQ
2567      * will increment from this new number henceforth.
2568      */
2569     data->state.rtsp_next_client_CSeq = va_arg(param, long);
2570     break;
2571 
2572   case CURLOPT_RTSP_SERVER_CSEQ:
2573     /* Same as the above, but for server-initiated requests */
2574     data->state.rtsp_next_client_CSeq = va_arg(param, long);
2575     break;
2576 
2577   case CURLOPT_INTERLEAVEDATA:
2578     data->set.rtp_out = va_arg(param, void *);
2579     break;
2580   case CURLOPT_INTERLEAVEFUNCTION:
2581     /* Set the user defined RTP write function */
2582     data->set.fwrite_rtp = va_arg(param, curl_write_callback);
2583     break;
2584 
2585   case CURLOPT_WILDCARDMATCH:
2586     data->set.wildcardmatch = (0 != va_arg(param, long)) ? TRUE : FALSE;
2587     break;
2588   case CURLOPT_CHUNK_BGN_FUNCTION:
2589     data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
2590     break;
2591   case CURLOPT_CHUNK_END_FUNCTION:
2592     data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
2593     break;
2594   case CURLOPT_FNMATCH_FUNCTION:
2595     data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
2596     break;
2597   case CURLOPT_CHUNK_DATA:
2598     data->wildcard.customptr = va_arg(param, void *);
2599     break;
2600   case CURLOPT_FNMATCH_DATA:
2601     data->set.fnmatch_data = va_arg(param, void *);
2602     break;
2603 #ifdef USE_TLS_SRP
2604   case CURLOPT_TLSAUTH_USERNAME:
2605     result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
2606                        va_arg(param, char *));
2607     if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
2608       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2609     break;
2610   case CURLOPT_TLSAUTH_PASSWORD:
2611     result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
2612                        va_arg(param, char *));
2613     if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
2614       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2615     break;
2616   case CURLOPT_TLSAUTH_TYPE:
2617     if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
2618       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
2619     else
2620       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
2621     break;
2622 #endif
2623   case CURLOPT_DNS_SERVERS:
2624     result = Curl_set_dns_servers(data, va_arg(param, char *));
2625     break;
2626   case CURLOPT_DNS_INTERFACE:
2627     result = Curl_set_dns_interface(data, va_arg(param, char *));
2628     break;
2629   case CURLOPT_DNS_LOCAL_IP4:
2630     result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
2631     break;
2632   case CURLOPT_DNS_LOCAL_IP6:
2633     result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
2634     break;
2635 
2636   case CURLOPT_TCP_KEEPALIVE:
2637     data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
2638     break;
2639   case CURLOPT_TCP_KEEPIDLE:
2640     data->set.tcp_keepidle = va_arg(param, long);
2641     break;
2642   case CURLOPT_TCP_KEEPINTVL:
2643     data->set.tcp_keepintvl = va_arg(param, long);
2644     break;
2645   case CURLOPT_TCP_FASTOPEN:
2646 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
2647     data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
2648 #else
2649     result = CURLE_NOT_BUILT_IN;
2650 #endif
2651     break;
2652   case CURLOPT_SSL_ENABLE_NPN:
2653     data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2654     break;
2655   case CURLOPT_SSL_ENABLE_ALPN:
2656     data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2657     break;
2658 
2659 #ifdef USE_UNIX_SOCKETS
2660   case CURLOPT_UNIX_SOCKET_PATH:
2661     result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2662                        va_arg(param, char *));
2663     break;
2664 #endif
2665 
2666   case CURLOPT_PATH_AS_IS:
2667     data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
2668     break;
2669   case CURLOPT_PIPEWAIT:
2670     data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
2671     break;
2672   case CURLOPT_STREAM_WEIGHT:
2673 #ifndef USE_NGHTTP2
2674     return CURLE_NOT_BUILT_IN;
2675 #else
2676     arg = va_arg(param, long);
2677     if((arg>=1) && (arg <= 256))
2678       data->set.stream_weight = (int)arg;
2679     break;
2680 #endif
2681   case CURLOPT_STREAM_DEPENDS:
2682   case CURLOPT_STREAM_DEPENDS_E:
2683   {
2684 #ifndef USE_NGHTTP2
2685     return CURLE_NOT_BUILT_IN;
2686 #else
2687     struct SessionHandle *dep = va_arg(param, struct SessionHandle *);
2688     if(dep && GOOD_EASY_HANDLE(dep)) {
2689       data->set.stream_depends_on = dep;
2690       data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
2691     }
2692     break;
2693 #endif
2694   }
2695   case CURLOPT_CONNECT_TO:
2696     data->set.connect_to = va_arg(param, struct curl_slist *);
2697     break;
2698   default:
2699     /* unknown tag and its companion, just ignore: */
2700     result = CURLE_UNKNOWN_OPTION;
2701     break;
2702   }
2703 
2704   return result;
2705 }
2706 
2707 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
conn_reset_postponed_data(struct connectdata * conn,int num)2708 static void conn_reset_postponed_data(struct connectdata *conn, int num)
2709 {
2710   struct postponed_data * const psnd = &(conn->postponed[num]);
2711   if(psnd->buffer) {
2712     DEBUGASSERT(psnd->allocated_size > 0);
2713     DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
2714     DEBUGASSERT(psnd->recv_size ?
2715                 (psnd->recv_processed < psnd->recv_size) :
2716                 (psnd->recv_processed == 0));
2717     DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
2718     free(psnd->buffer);
2719     psnd->buffer = NULL;
2720     psnd->allocated_size = 0;
2721     psnd->recv_size = 0;
2722     psnd->recv_processed = 0;
2723 #ifdef DEBUGBUILD
2724     psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
2725 #endif /* DEBUGBUILD */
2726   }
2727   else {
2728     DEBUGASSERT (psnd->allocated_size == 0);
2729     DEBUGASSERT (psnd->recv_size == 0);
2730     DEBUGASSERT (psnd->recv_processed == 0);
2731     DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
2732   }
2733 }
2734 
conn_reset_all_postponed_data(struct connectdata * conn)2735 static void conn_reset_all_postponed_data(struct connectdata *conn)
2736 {
2737   conn_reset_postponed_data(conn, 0);
2738   conn_reset_postponed_data(conn, 1);
2739 }
2740 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
2741 /* Use "do-nothing" macros instead of functions when workaround not used */
2742 #define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
2743 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
2744 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
2745 
conn_free(struct connectdata * conn)2746 static void conn_free(struct connectdata *conn)
2747 {
2748   if(!conn)
2749     return;
2750 
2751   /* possible left-overs from the async name resolvers */
2752   Curl_resolver_cancel(conn);
2753 
2754   /* close the SSL stuff before we close any sockets since they will/may
2755      write to the sockets */
2756   Curl_ssl_close(conn, FIRSTSOCKET);
2757   Curl_ssl_close(conn, SECONDARYSOCKET);
2758 
2759   /* close possibly still open sockets */
2760   if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
2761     Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
2762   if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
2763     Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
2764   if(CURL_SOCKET_BAD != conn->tempsock[0])
2765     Curl_closesocket(conn, conn->tempsock[0]);
2766   if(CURL_SOCKET_BAD != conn->tempsock[1])
2767     Curl_closesocket(conn, conn->tempsock[1]);
2768 
2769 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
2770     defined(NTLM_WB_ENABLED)
2771   Curl_ntlm_wb_cleanup(conn);
2772 #endif
2773 
2774   Curl_safefree(conn->user);
2775   Curl_safefree(conn->passwd);
2776   Curl_safefree(conn->oauth_bearer);
2777   Curl_safefree(conn->options);
2778   Curl_safefree(conn->proxyuser);
2779   Curl_safefree(conn->proxypasswd);
2780   Curl_safefree(conn->allocptr.proxyuserpwd);
2781   Curl_safefree(conn->allocptr.uagent);
2782   Curl_safefree(conn->allocptr.userpwd);
2783   Curl_safefree(conn->allocptr.accept_encoding);
2784   Curl_safefree(conn->allocptr.te);
2785   Curl_safefree(conn->allocptr.rangeline);
2786   Curl_safefree(conn->allocptr.ref);
2787   Curl_safefree(conn->allocptr.host);
2788   Curl_safefree(conn->allocptr.cookiehost);
2789   Curl_safefree(conn->allocptr.rtsp_transport);
2790   Curl_safefree(conn->trailer);
2791   Curl_safefree(conn->host.rawalloc); /* host name buffer */
2792   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
2793   Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
2794   Curl_safefree(conn->master_buffer);
2795 
2796   conn_reset_all_postponed_data(conn);
2797 
2798   Curl_llist_destroy(conn->send_pipe, NULL);
2799   Curl_llist_destroy(conn->recv_pipe, NULL);
2800 
2801   conn->send_pipe = NULL;
2802   conn->recv_pipe = NULL;
2803 
2804   Curl_safefree(conn->localdev);
2805   Curl_free_ssl_config(&conn->ssl_config);
2806 
2807   free(conn); /* free all the connection oriented data */
2808 }
2809 
2810 /*
2811  * Disconnects the given connection. Note the connection may not be the
2812  * primary connection, like when freeing room in the connection cache or
2813  * killing of a dead old connection.
2814  *
2815  * This function MUST NOT reset state in the SessionHandle struct if that
2816  * isn't strictly bound to the life-time of *this* particular connection.
2817  *
2818  */
2819 
Curl_disconnect(struct connectdata * conn,bool dead_connection)2820 CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
2821 {
2822   struct SessionHandle *data;
2823   if(!conn)
2824     return CURLE_OK; /* this is closed and fine already */
2825   data = conn->data;
2826 
2827   if(!data) {
2828     DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
2829     return CURLE_OK;
2830   }
2831 
2832   if(conn->dns_entry != NULL) {
2833     Curl_resolv_unlock(data, conn->dns_entry);
2834     conn->dns_entry = NULL;
2835   }
2836 
2837   Curl_hostcache_prune(data); /* kill old DNS cache entries */
2838 
2839 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
2840   /* Cleanup NTLM connection-related data */
2841   Curl_http_ntlm_cleanup(conn);
2842 #endif
2843 
2844   if(conn->handler->disconnect)
2845     /* This is set if protocol-specific cleanups should be made */
2846     conn->handler->disconnect(conn, dead_connection);
2847 
2848     /* unlink ourselves! */
2849   infof(data, "Closing connection %ld\n", conn->connection_id);
2850   Curl_conncache_remove_conn(data->state.conn_cache, conn);
2851 
2852   free_fixed_hostname(&conn->host);
2853   free_fixed_hostname(&conn->conn_to_host);
2854   free_fixed_hostname(&conn->proxy);
2855 
2856   Curl_ssl_close(conn, FIRSTSOCKET);
2857 
2858   /* Indicate to all handles on the pipe that we're dead */
2859   if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
2860     signalPipeClose(conn->send_pipe, TRUE);
2861     signalPipeClose(conn->recv_pipe, TRUE);
2862   }
2863 
2864   conn_free(conn);
2865 
2866   return CURLE_OK;
2867 }
2868 
2869 /*
2870  * This function should return TRUE if the socket is to be assumed to
2871  * be dead. Most commonly this happens when the server has closed the
2872  * connection due to inactivity.
2873  */
SocketIsDead(curl_socket_t sock)2874 static bool SocketIsDead(curl_socket_t sock)
2875 {
2876   int sval;
2877   bool ret_val = TRUE;
2878 
2879   sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
2880   if(sval == 0)
2881     /* timeout */
2882     ret_val = FALSE;
2883 
2884   return ret_val;
2885 }
2886 
2887 /*
2888  * IsPipeliningPossible() returns TRUE if the options set would allow
2889  * pipelining/multiplexing and the connection is using a HTTP protocol.
2890  */
IsPipeliningPossible(const struct SessionHandle * handle,const struct connectdata * conn)2891 static bool IsPipeliningPossible(const struct SessionHandle *handle,
2892                                  const struct connectdata *conn)
2893 {
2894   /* If a HTTP protocol and pipelining is enabled */
2895   if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
2896 
2897     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
2898        (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
2899        (handle->set.httpreq == HTTPREQ_GET ||
2900         handle->set.httpreq == HTTPREQ_HEAD))
2901       /* didn't ask for HTTP/1.0 and a GET or HEAD */
2902       return TRUE;
2903 
2904     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
2905        (handle->set.httpversion >= CURL_HTTP_VERSION_2))
2906       /* allows HTTP/2 */
2907       return TRUE;
2908   }
2909   return FALSE;
2910 }
2911 
Curl_removeHandleFromPipeline(struct SessionHandle * handle,struct curl_llist * pipeline)2912 int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
2913                                   struct curl_llist *pipeline)
2914 {
2915   if(pipeline) {
2916     struct curl_llist_element *curr;
2917 
2918     curr = pipeline->head;
2919     while(curr) {
2920       if(curr->ptr == handle) {
2921         Curl_llist_remove(pipeline, curr, NULL);
2922         return 1; /* we removed a handle */
2923       }
2924       curr = curr->next;
2925     }
2926   }
2927 
2928   return 0;
2929 }
2930 
2931 #if 0 /* this code is saved here as it is useful for debugging purposes */
2932 static void Curl_printPipeline(struct curl_llist *pipeline)
2933 {
2934   struct curl_llist_element *curr;
2935 
2936   curr = pipeline->head;
2937   while(curr) {
2938     struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
2939     infof(data, "Handle in pipeline: %s\n", data->state.path);
2940     curr = curr->next;
2941   }
2942 }
2943 #endif
2944 
gethandleathead(struct curl_llist * pipeline)2945 static struct SessionHandle* gethandleathead(struct curl_llist *pipeline)
2946 {
2947   struct curl_llist_element *curr = pipeline->head;
2948   if(curr) {
2949     return (struct SessionHandle *) curr->ptr;
2950   }
2951 
2952   return NULL;
2953 }
2954 
2955 /* remove the specified connection from all (possible) pipelines and related
2956    queues */
Curl_getoff_all_pipelines(struct SessionHandle * data,struct connectdata * conn)2957 void Curl_getoff_all_pipelines(struct SessionHandle *data,
2958                                struct connectdata *conn)
2959 {
2960   bool recv_head = (conn->readchannel_inuse &&
2961                     Curl_recvpipe_head(data, conn));
2962   bool send_head = (conn->writechannel_inuse &&
2963                     Curl_sendpipe_head(data, conn));
2964 
2965   if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
2966     Curl_pipeline_leave_read(conn);
2967   if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
2968     Curl_pipeline_leave_write(conn);
2969 }
2970 
signalPipeClose(struct curl_llist * pipeline,bool pipe_broke)2971 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
2972 {
2973   struct curl_llist_element *curr;
2974 
2975   if(!pipeline)
2976     return;
2977 
2978   curr = pipeline->head;
2979   while(curr) {
2980     struct curl_llist_element *next = curr->next;
2981     struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
2982 
2983 #ifdef DEBUGBUILD /* debug-only code */
2984     if(data->magic != CURLEASY_MAGIC_NUMBER) {
2985       /* MAJOR BADNESS */
2986       infof(data, "signalPipeClose() found BAAD easy handle\n");
2987     }
2988 #endif
2989 
2990     if(pipe_broke)
2991       data->state.pipe_broke = TRUE;
2992     Curl_multi_handlePipeBreak(data);
2993     Curl_llist_remove(pipeline, curr, NULL);
2994     curr = next;
2995   }
2996 }
2997 
2998 /*
2999  * This function finds the connection in the connection
3000  * cache that has been unused for the longest time.
3001  *
3002  * Returns the pointer to the oldest idle connection, or NULL if none was
3003  * found.
3004  */
3005 struct connectdata *
Curl_oldest_idle_connection(struct SessionHandle * data)3006 Curl_oldest_idle_connection(struct SessionHandle *data)
3007 {
3008   struct conncache *bc = data->state.conn_cache;
3009   struct curl_hash_iterator iter;
3010   struct curl_llist_element *curr;
3011   struct curl_hash_element *he;
3012   long highscore=-1;
3013   long score;
3014   struct timeval now;
3015   struct connectdata *conn_candidate = NULL;
3016   struct connectbundle *bundle;
3017 
3018   now = Curl_tvnow();
3019 
3020   Curl_hash_start_iterate(&bc->hash, &iter);
3021 
3022   he = Curl_hash_next_element(&iter);
3023   while(he) {
3024     struct connectdata *conn;
3025 
3026     bundle = he->ptr;
3027 
3028     curr = bundle->conn_list->head;
3029     while(curr) {
3030       conn = curr->ptr;
3031 
3032       if(!conn->inuse) {
3033         /* Set higher score for the age passed since the connection was used */
3034         score = Curl_tvdiff(now, conn->now);
3035 
3036         if(score > highscore) {
3037           highscore = score;
3038           conn_candidate = conn;
3039         }
3040       }
3041       curr = curr->next;
3042     }
3043 
3044     he = Curl_hash_next_element(&iter);
3045   }
3046 
3047   return conn_candidate;
3048 }
3049 
3050 /*
3051  * This function finds the connection in the connection
3052  * bundle that has been unused for the longest time.
3053  *
3054  * Returns the pointer to the oldest idle connection, or NULL if none was
3055  * found.
3056  */
3057 static struct connectdata *
find_oldest_idle_connection_in_bundle(struct SessionHandle * data,struct connectbundle * bundle)3058 find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
3059                                       struct connectbundle *bundle)
3060 {
3061   struct curl_llist_element *curr;
3062   long highscore=-1;
3063   long score;
3064   struct timeval now;
3065   struct connectdata *conn_candidate = NULL;
3066   struct connectdata *conn;
3067 
3068   (void)data;
3069 
3070   now = Curl_tvnow();
3071 
3072   curr = bundle->conn_list->head;
3073   while(curr) {
3074     conn = curr->ptr;
3075 
3076     if(!conn->inuse) {
3077       /* Set higher score for the age passed since the connection was used */
3078       score = Curl_tvdiff(now, conn->now);
3079 
3080       if(score > highscore) {
3081         highscore = score;
3082         conn_candidate = conn;
3083       }
3084     }
3085     curr = curr->next;
3086   }
3087 
3088   return conn_candidate;
3089 }
3090 
3091 /*
3092  * This function checks if given connection is dead and disconnects if so.
3093  * (That also removes it from the connection cache.)
3094  *
3095  * Returns TRUE if the connection actually was dead and disconnected.
3096  */
disconnect_if_dead(struct connectdata * conn,struct SessionHandle * data)3097 static bool disconnect_if_dead(struct connectdata *conn,
3098                                struct SessionHandle *data)
3099 {
3100   size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
3101   if(!pipeLen && !conn->inuse) {
3102     /* The check for a dead socket makes sense only if there are no
3103        handles in pipeline and the connection isn't already marked in
3104        use */
3105     bool dead;
3106     if(conn->handler->protocol & CURLPROTO_RTSP)
3107       /* RTSP is a special case due to RTP interleaving */
3108       dead = Curl_rtsp_connisdead(conn);
3109     else
3110       dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
3111 
3112     if(dead) {
3113       conn->data = data;
3114       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
3115 
3116       /* disconnect resources */
3117       Curl_disconnect(conn, /* dead_connection */TRUE);
3118       return TRUE;
3119     }
3120   }
3121   return FALSE;
3122 }
3123 
3124 /*
3125  * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach()
3126  *
3127  * Returns always 0.
3128  */
call_disconnect_if_dead(struct connectdata * conn,void * param)3129 static int call_disconnect_if_dead(struct connectdata *conn,
3130                                       void *param)
3131 {
3132   struct SessionHandle* data = (struct SessionHandle*)param;
3133   disconnect_if_dead(conn, data);
3134   return 0; /* continue iteration */
3135 }
3136 
3137 /*
3138  * This function scans the connection cache for half-open/dead connections,
3139  * closes and removes them.
3140  * The cleanup is done at most once per second.
3141  */
prune_dead_connections(struct SessionHandle * data)3142 static void prune_dead_connections(struct SessionHandle *data)
3143 {
3144   struct timeval now = Curl_tvnow();
3145   long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
3146 
3147   if(elapsed >= 1000L) {
3148     Curl_conncache_foreach(data->state.conn_cache, data,
3149                            call_disconnect_if_dead);
3150     data->state.conn_cache->last_cleanup = now;
3151   }
3152 }
3153 
3154 
max_pipeline_length(struct Curl_multi * multi)3155 static size_t max_pipeline_length(struct Curl_multi *multi)
3156 {
3157   return multi ? multi->max_pipeline_length : 0;
3158 }
3159 
3160 
3161 /*
3162  * Given one filled in connection struct (named needle), this function should
3163  * detect if there already is one that has all the significant details
3164  * exactly the same and thus should be used instead.
3165  *
3166  * If there is a match, this function returns TRUE - and has marked the
3167  * connection as 'in-use'. It must later be called with ConnectionDone() to
3168  * return back to 'idle' (unused) state.
3169  *
3170  * The force_reuse flag is set if the connection must be used, even if
3171  * the pipelining strategy wants to open a new connection instead of reusing.
3172  */
3173 static bool
ConnectionExists(struct SessionHandle * data,struct connectdata * needle,struct connectdata ** usethis,bool * force_reuse,bool * waitpipe)3174 ConnectionExists(struct SessionHandle *data,
3175                  struct connectdata *needle,
3176                  struct connectdata **usethis,
3177                  bool *force_reuse,
3178                  bool *waitpipe)
3179 {
3180   struct connectdata *check;
3181   struct connectdata *chosen = 0;
3182   bool foundPendingCandidate = FALSE;
3183   bool canPipeline = IsPipeliningPossible(data, needle);
3184   struct connectbundle *bundle;
3185 
3186 #ifdef USE_NTLM
3187   bool wantNTLMhttp = ((data->state.authhost.want &
3188                       (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3189                       (needle->handler->protocol & PROTO_FAMILY_HTTP));
3190   bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
3191                            ((data->state.authproxy.want &
3192                            (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3193                            (needle->handler->protocol & PROTO_FAMILY_HTTP)));
3194 #endif
3195 
3196   *force_reuse = FALSE;
3197   *waitpipe = FALSE;
3198 
3199   /* We can't pipe if the site is blacklisted */
3200   if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
3201     canPipeline = FALSE;
3202   }
3203 
3204   /* Look up the bundle with all the connections to this
3205      particular host */
3206   bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
3207   if(bundle) {
3208     /* Max pipe length is zero (unlimited) for multiplexed connections */
3209     size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)?
3210       max_pipeline_length(data->multi):0;
3211     size_t best_pipe_len = max_pipe_len;
3212     struct curl_llist_element *curr;
3213     const char *hostname;
3214 
3215     if(needle->bits.conn_to_host)
3216       hostname = needle->conn_to_host.name;
3217     else
3218       hostname = needle->host.name;
3219 
3220     infof(data, "Found bundle for host %s: %p [%s]\n",
3221           hostname, (void *)bundle,
3222           (bundle->multiuse== BUNDLE_PIPELINING?
3223            "can pipeline":
3224            (bundle->multiuse== BUNDLE_MULTIPLEX?
3225             "can multiplex":"serially")));
3226 
3227     /* We can't pipe if we don't know anything about the server */
3228     if(canPipeline) {
3229       if(bundle->multiuse <= BUNDLE_UNKNOWN) {
3230         if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
3231           infof(data, "Server doesn't support multi-use yet, wait\n");
3232           *waitpipe = TRUE;
3233           return FALSE; /* no re-use */
3234         }
3235 
3236         infof(data, "Server doesn't support multi-use (yet)\n");
3237         canPipeline = FALSE;
3238       }
3239       if((bundle->multiuse == BUNDLE_PIPELINING) &&
3240          !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
3241         /* not asked for, switch off */
3242         infof(data, "Could pipeline, but not asked to!\n");
3243         canPipeline = FALSE;
3244       }
3245       else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
3246               !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
3247         infof(data, "Could multiplex, but not asked to!\n");
3248         canPipeline = FALSE;
3249       }
3250     }
3251 
3252     curr = bundle->conn_list->head;
3253     while(curr) {
3254       bool match = FALSE;
3255       size_t pipeLen;
3256 
3257       /*
3258        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
3259        * check connections to that proxy and not to the actual remote server.
3260        */
3261       check = curr->ptr;
3262       curr = curr->next;
3263 
3264       if(disconnect_if_dead(check, data))
3265         continue;
3266 
3267       pipeLen = check->send_pipe->size + check->recv_pipe->size;
3268 
3269       if(canPipeline) {
3270 
3271         if(!check->bits.multiplex) {
3272           /* If not multiplexing, make sure the pipe has only GET requests */
3273           struct SessionHandle* sh = gethandleathead(check->send_pipe);
3274           struct SessionHandle* rh = gethandleathead(check->recv_pipe);
3275           if(sh) {
3276             if(!IsPipeliningPossible(sh, check))
3277               continue;
3278           }
3279           else if(rh) {
3280             if(!IsPipeliningPossible(rh, check))
3281               continue;
3282           }
3283         }
3284       }
3285       else {
3286         if(pipeLen > 0) {
3287           /* can only happen within multi handles, and means that another easy
3288              handle is using this connection */
3289           continue;
3290         }
3291 
3292         if(Curl_resolver_asynch()) {
3293           /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
3294              completed yet and until then we don't re-use this connection */
3295           if(!check->ip_addr_str[0]) {
3296             infof(data,
3297                   "Connection #%ld is still name resolving, can't reuse\n",
3298                   check->connection_id);
3299             continue;
3300           }
3301         }
3302 
3303         if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
3304            check->bits.close) {
3305           if(!check->bits.close)
3306             foundPendingCandidate = TRUE;
3307           /* Don't pick a connection that hasn't connected yet or that is going
3308              to get closed. */
3309           infof(data, "Connection #%ld isn't open enough, can't reuse\n",
3310                 check->connection_id);
3311 #ifdef DEBUGBUILD
3312           if(check->recv_pipe->size > 0) {
3313             infof(data,
3314                   "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
3315                   check->connection_id);
3316           }
3317 #endif
3318           continue;
3319         }
3320       }
3321 
3322       if((needle->handler->flags&PROTOPT_SSL) !=
3323          (check->handler->flags&PROTOPT_SSL))
3324         /* don't do mixed SSL and non-SSL connections */
3325         if(get_protocol_family(check->handler->protocol) !=
3326            needle->handler->protocol || !check->tls_upgraded)
3327           /* except protocols that have been upgraded via TLS */
3328           continue;
3329 
3330       if(needle->handler->flags&PROTOPT_SSL) {
3331         if((data->set.ssl.verifypeer != check->verifypeer) ||
3332            (data->set.ssl.verifyhost != check->verifyhost))
3333           continue;
3334       }
3335 
3336       if(needle->bits.proxy != check->bits.proxy)
3337         /* don't do mixed proxy and non-proxy connections */
3338         continue;
3339 
3340       if(needle->bits.proxy &&
3341          (needle->proxytype != check->proxytype ||
3342           needle->bits.httpproxy != check->bits.httpproxy ||
3343           needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
3344           !Curl_raw_equal(needle->proxy.name, check->proxy.name) ||
3345           needle->port != check->port))
3346         /* don't mix connections that use different proxies */
3347         continue;
3348 
3349       if(needle->bits.conn_to_host != check->bits.conn_to_host)
3350         /* don't mix connections that use the "connect to host" feature and
3351          * connections that don't use this feature */
3352         continue;
3353 
3354       if(needle->bits.conn_to_port != check->bits.conn_to_port)
3355         /* don't mix connections that use the "connect to port" feature and
3356          * connections that don't use this feature */
3357         continue;
3358 
3359       if(!canPipeline && check->inuse)
3360         /* this request can't be pipelined but the checked connection is
3361            already in use so we skip it */
3362         continue;
3363 
3364       if(needle->localdev || needle->localport) {
3365         /* If we are bound to a specific local end (IP+port), we must not
3366            re-use a random other one, although if we didn't ask for a
3367            particular one we can reuse one that was bound.
3368 
3369            This comparison is a bit rough and too strict. Since the input
3370            parameters can be specified in numerous ways and still end up the
3371            same it would take a lot of processing to make it really accurate.
3372            Instead, this matching will assume that re-uses of bound connections
3373            will most likely also re-use the exact same binding parameters and
3374            missing out a few edge cases shouldn't hurt anyone very much.
3375         */
3376         if((check->localport != needle->localport) ||
3377            (check->localportrange != needle->localportrange) ||
3378            !check->localdev ||
3379            !needle->localdev ||
3380            strcmp(check->localdev, needle->localdev))
3381           continue;
3382       }
3383 
3384       if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
3385         /* This protocol requires credentials per connection,
3386            so verify that we're using the same name and password as well */
3387         if(!strequal(needle->user, check->user) ||
3388            !strequal(needle->passwd, check->passwd)) {
3389           /* one of them was different */
3390           continue;
3391         }
3392       }
3393 
3394       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
3395          (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
3396         /* The requested connection does not use a HTTP proxy or it uses SSL or
3397            it is a non-SSL protocol tunneled over the same HTTP proxy name and
3398            port number */
3399         if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
3400             (get_protocol_family(check->handler->protocol) ==
3401              needle->handler->protocol && check->tls_upgraded)) &&
3402            (!needle->bits.conn_to_host || Curl_raw_equal(
3403             needle->conn_to_host.name, check->conn_to_host.name)) &&
3404            (!needle->bits.conn_to_port ||
3405              needle->conn_to_port == check->conn_to_port) &&
3406            Curl_raw_equal(needle->host.name, check->host.name) &&
3407            needle->remote_port == check->remote_port) {
3408           /* The schemes match or the the protocol family is the same and the
3409              previous connection was TLS upgraded, and the hostname and host
3410              port match */
3411           if(needle->handler->flags & PROTOPT_SSL) {
3412             /* This is a SSL connection so verify that we're using the same
3413                SSL options as well */
3414             if(!Curl_ssl_config_matches(&needle->ssl_config,
3415                                         &check->ssl_config)) {
3416               DEBUGF(infof(data,
3417                            "Connection #%ld has different SSL parameters, "
3418                            "can't reuse\n",
3419                            check->connection_id));
3420               continue;
3421             }
3422             else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
3423               foundPendingCandidate = TRUE;
3424               DEBUGF(infof(data,
3425                            "Connection #%ld has not started SSL connect, "
3426                            "can't reuse\n",
3427                            check->connection_id));
3428               continue;
3429             }
3430           }
3431           match = TRUE;
3432         }
3433       }
3434       else {
3435         /* The requested connection is using the same HTTP proxy in normal
3436            mode (no tunneling) */
3437         match = TRUE;
3438       }
3439 
3440       if(match) {
3441 #if defined(USE_NTLM)
3442         /* If we are looking for an HTTP+NTLM connection, check if this is
3443            already authenticating with the right credentials. If not, keep
3444            looking so that we can reuse NTLM connections if
3445            possible. (Especially we must not reuse the same connection if
3446            partway through a handshake!) */
3447         if(wantNTLMhttp) {
3448           if(!strequal(needle->user, check->user) ||
3449              !strequal(needle->passwd, check->passwd))
3450             continue;
3451         }
3452         else if(check->ntlm.state != NTLMSTATE_NONE) {
3453           /* Connection is using NTLM auth but we don't want NTLM */
3454           continue;
3455         }
3456 
3457         /* Same for Proxy NTLM authentication */
3458         if(wantProxyNTLMhttp) {
3459           /* Both check->proxyuser and check->proxypasswd can be NULL */
3460           if(!check->proxyuser || !check->proxypasswd)
3461             continue;
3462 
3463           if(!strequal(needle->proxyuser, check->proxyuser) ||
3464              !strequal(needle->proxypasswd, check->proxypasswd))
3465             continue;
3466         }
3467         else if(check->proxyntlm.state != NTLMSTATE_NONE) {
3468           /* Proxy connection is using NTLM auth but we don't want NTLM */
3469           continue;
3470         }
3471 
3472         if(wantNTLMhttp || wantProxyNTLMhttp) {
3473           /* Credentials are already checked, we can use this connection */
3474           chosen = check;
3475 
3476           if((wantNTLMhttp &&
3477              (check->ntlm.state != NTLMSTATE_NONE)) ||
3478               (wantProxyNTLMhttp &&
3479                (check->proxyntlm.state != NTLMSTATE_NONE))) {
3480             /* We must use this connection, no other */
3481             *force_reuse = TRUE;
3482             break;
3483           }
3484 
3485           /* Continue look up for a better connection */
3486           continue;
3487         }
3488 #endif
3489         if(canPipeline) {
3490           /* We can pipeline if we want to. Let's continue looking for
3491              the optimal connection to use, i.e the shortest pipe that is not
3492              blacklisted. */
3493 
3494           if(pipeLen == 0) {
3495             /* We have the optimal connection. Let's stop looking. */
3496             chosen = check;
3497             break;
3498           }
3499 
3500           /* We can't use the connection if the pipe is full */
3501           if(max_pipe_len && (pipeLen >= max_pipe_len)) {
3502             infof(data, "Pipe is full, skip (%zu)\n", pipeLen);
3503             continue;
3504           }
3505 #ifdef USE_NGHTTP2
3506           /* If multiplexed, make sure we don't go over concurrency limit */
3507           if(check->bits.multiplex) {
3508             /* Multiplexed connections can only be HTTP/2 for now */
3509             struct http_conn *httpc = &check->proto.httpc;
3510             if(pipeLen >= httpc->settings.max_concurrent_streams) {
3511               infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
3512                     pipeLen);
3513               continue;
3514             }
3515           }
3516 #endif
3517           /* We can't use the connection if the pipe is penalized */
3518           if(Curl_pipeline_penalized(data, check)) {
3519             infof(data, "Penalized, skip\n");
3520             continue;
3521           }
3522 
3523           if(max_pipe_len) {
3524             if(pipeLen < best_pipe_len) {
3525               /* This connection has a shorter pipe so far. We'll pick this
3526                  and continue searching */
3527               chosen = check;
3528               best_pipe_len = pipeLen;
3529               continue;
3530             }
3531           }
3532           else {
3533             /* When not pipelining (== multiplexed), we have a match here! */
3534             chosen = check;
3535             infof(data, "Multiplexed connection found!\n");
3536             break;
3537           }
3538         }
3539         else {
3540           /* We have found a connection. Let's stop searching. */
3541           chosen = check;
3542           break;
3543         }
3544       }
3545     }
3546   }
3547 
3548   if(chosen) {
3549     *usethis = chosen;
3550     return TRUE; /* yes, we found one to use! */
3551   }
3552 
3553   if(foundPendingCandidate && data->set.pipewait) {
3554     infof(data,
3555           "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
3556     *waitpipe = TRUE;
3557   }
3558 
3559   return FALSE; /* no matching connecting exists */
3560 }
3561 
3562 /* after a TCP connection to the proxy has been verified, this function does
3563    the next magic step.
3564 
3565    Note: this function's sub-functions call failf()
3566 
3567 */
Curl_connected_proxy(struct connectdata * conn,int sockindex)3568 CURLcode Curl_connected_proxy(struct connectdata *conn,
3569                               int sockindex)
3570 {
3571   if(!conn->bits.proxy || sockindex)
3572     /* this magic only works for the primary socket as the secondary is used
3573        for FTP only and it has FTP specific magic in ftp.c */
3574     return CURLE_OK;
3575 
3576   switch(conn->proxytype) {
3577 #ifndef CURL_DISABLE_PROXY
3578   case CURLPROXY_SOCKS5:
3579   case CURLPROXY_SOCKS5_HOSTNAME:
3580     return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
3581                        conn->bits.conn_to_host ? conn->conn_to_host.name :
3582                        conn->host.name,
3583                        conn->bits.conn_to_port ? conn->conn_to_port :
3584                        conn->remote_port,
3585                        FIRSTSOCKET, conn);
3586 
3587   case CURLPROXY_SOCKS4:
3588     return Curl_SOCKS4(conn->proxyuser,
3589                        conn->bits.conn_to_host ? conn->conn_to_host.name :
3590                        conn->host.name,
3591                        conn->bits.conn_to_port ? conn->conn_to_port :
3592                        conn->remote_port,
3593                        FIRSTSOCKET, conn, FALSE);
3594 
3595   case CURLPROXY_SOCKS4A:
3596     return Curl_SOCKS4(conn->proxyuser,
3597                        conn->bits.conn_to_host ? conn->conn_to_host.name :
3598                        conn->host.name,
3599                        conn->bits.conn_to_port ? conn->conn_to_port :
3600                        conn->remote_port,
3601                        FIRSTSOCKET, conn, TRUE);
3602 
3603 #endif /* CURL_DISABLE_PROXY */
3604   case CURLPROXY_HTTP:
3605   case CURLPROXY_HTTP_1_0:
3606     /* do nothing here. handled later. */
3607     break;
3608   default:
3609     break;
3610   } /* switch proxytype */
3611 
3612   return CURLE_OK;
3613 }
3614 
3615 /*
3616  * verboseconnect() displays verbose information after a connect
3617  */
3618 #ifndef CURL_DISABLE_VERBOSE_STRINGS
Curl_verboseconnect(struct connectdata * conn)3619 void Curl_verboseconnect(struct connectdata *conn)
3620 {
3621   if(conn->data->set.verbose)
3622     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
3623           conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
3624           conn->ip_addr_str, conn->port, conn->connection_id);
3625 }
3626 #endif
3627 
Curl_protocol_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)3628 int Curl_protocol_getsock(struct connectdata *conn,
3629                           curl_socket_t *socks,
3630                           int numsocks)
3631 {
3632   if(conn->handler->proto_getsock)
3633     return conn->handler->proto_getsock(conn, socks, numsocks);
3634   return GETSOCK_BLANK;
3635 }
3636 
Curl_doing_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)3637 int Curl_doing_getsock(struct connectdata *conn,
3638                        curl_socket_t *socks,
3639                        int numsocks)
3640 {
3641   if(conn && conn->handler->doing_getsock)
3642     return conn->handler->doing_getsock(conn, socks, numsocks);
3643   return GETSOCK_BLANK;
3644 }
3645 
3646 /*
3647  * We are doing protocol-specific connecting and this is being called over and
3648  * over from the multi interface until the connection phase is done on
3649  * protocol layer.
3650  */
3651 
Curl_protocol_connecting(struct connectdata * conn,bool * done)3652 CURLcode Curl_protocol_connecting(struct connectdata *conn,
3653                                   bool *done)
3654 {
3655   CURLcode result=CURLE_OK;
3656 
3657   if(conn && conn->handler->connecting) {
3658     *done = FALSE;
3659     result = conn->handler->connecting(conn, done);
3660   }
3661   else
3662     *done = TRUE;
3663 
3664   return result;
3665 }
3666 
3667 /*
3668  * We are DOING this is being called over and over from the multi interface
3669  * until the DOING phase is done on protocol layer.
3670  */
3671 
Curl_protocol_doing(struct connectdata * conn,bool * done)3672 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
3673 {
3674   CURLcode result=CURLE_OK;
3675 
3676   if(conn && conn->handler->doing) {
3677     *done = FALSE;
3678     result = conn->handler->doing(conn, done);
3679   }
3680   else
3681     *done = TRUE;
3682 
3683   return result;
3684 }
3685 
3686 /*
3687  * We have discovered that the TCP connection has been successful, we can now
3688  * proceed with some action.
3689  *
3690  */
Curl_protocol_connect(struct connectdata * conn,bool * protocol_done)3691 CURLcode Curl_protocol_connect(struct connectdata *conn,
3692                                bool *protocol_done)
3693 {
3694   CURLcode result=CURLE_OK;
3695 
3696   *protocol_done = FALSE;
3697 
3698   if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
3699     /* We already are connected, get back. This may happen when the connect
3700        worked fine in the first call, like when we connect to a local server
3701        or proxy. Note that we don't know if the protocol is actually done.
3702 
3703        Unless this protocol doesn't have any protocol-connect callback, as
3704        then we know we're done. */
3705     if(!conn->handler->connecting)
3706       *protocol_done = TRUE;
3707 
3708     return CURLE_OK;
3709   }
3710 
3711   if(!conn->bits.protoconnstart) {
3712 
3713     result = Curl_proxy_connect(conn);
3714     if(result)
3715       return result;
3716 
3717     if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
3718        (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
3719       /* when using an HTTP tunnel proxy, await complete tunnel establishment
3720          before proceeding further. Return CURLE_OK so we'll be called again */
3721       return CURLE_OK;
3722 
3723     if(conn->handler->connect_it) {
3724       /* is there a protocol-specific connect() procedure? */
3725 
3726       /* Call the protocol-specific connect function */
3727       result = conn->handler->connect_it(conn, protocol_done);
3728     }
3729     else
3730       *protocol_done = TRUE;
3731 
3732     /* it has started, possibly even completed but that knowledge isn't stored
3733        in this bit! */
3734     if(!result)
3735       conn->bits.protoconnstart = TRUE;
3736   }
3737 
3738   return result; /* pass back status */
3739 }
3740 
3741 /*
3742  * Helpers for IDNA convertions.
3743  */
is_ASCII_name(const char * hostname)3744 static bool is_ASCII_name(const char *hostname)
3745 {
3746   const unsigned char *ch = (const unsigned char*)hostname;
3747 
3748   while(*ch) {
3749     if(*ch++ & 0x80)
3750       return FALSE;
3751   }
3752   return TRUE;
3753 }
3754 
3755 #ifdef USE_LIBIDN
3756 /*
3757  * Check if characters in hostname is allowed in Top Level Domain.
3758  */
tld_check_name(struct SessionHandle * data,const char * ace_hostname)3759 static bool tld_check_name(struct SessionHandle *data,
3760                            const char *ace_hostname)
3761 {
3762   size_t err_pos;
3763   char *uc_name = NULL;
3764   int rc;
3765 #ifndef CURL_DISABLE_VERBOSE_STRINGS
3766   const char *tld_errmsg = "<no msg>";
3767 #else
3768   (void)data;
3769 #endif
3770 
3771   /* Convert (and downcase) ACE-name back into locale's character set */
3772   rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
3773   if(rc != IDNA_SUCCESS)
3774     return FALSE;
3775 
3776   /* Warning: err_pos receives "the decoded character offset rather than the
3777      byte position in the string." And as of libidn 1.32 that character offset
3778      is for UTF-8, even if the passed in string is another locale. */
3779   rc = tld_check_lz(uc_name, &err_pos, NULL);
3780 #ifndef CURL_DISABLE_VERBOSE_STRINGS
3781 #ifdef HAVE_TLD_STRERROR
3782   if(rc != TLD_SUCCESS)
3783     tld_errmsg = tld_strerror((Tld_rc)rc);
3784 #endif
3785   if(rc != TLD_SUCCESS)
3786     infof(data, "WARNING: TLD check for %s failed; %s\n",
3787           uc_name, tld_errmsg);
3788 #endif /* CURL_DISABLE_VERBOSE_STRINGS */
3789   if(uc_name)
3790      idn_free(uc_name);
3791   if(rc != TLD_SUCCESS)
3792     return FALSE;
3793 
3794   return TRUE;
3795 }
3796 #endif
3797 
3798 /*
3799  * Perform any necessary IDN conversion of hostname
3800  */
fix_hostname(struct SessionHandle * data,struct connectdata * conn,struct hostname * host)3801 static void fix_hostname(struct SessionHandle *data,
3802                          struct connectdata *conn, struct hostname *host)
3803 {
3804   size_t len;
3805 
3806 #ifndef USE_LIBIDN
3807   (void)data;
3808   (void)conn;
3809 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
3810   (void)conn;
3811 #endif
3812 
3813   /* set the name we use to display the host name */
3814   host->dispname = host->name;
3815 
3816   len = strlen(host->name);
3817   if(len && (host->name[len-1] == '.'))
3818     /* strip off a single trailing dot if present, primarily for SNI but
3819        there's no use for it */
3820     host->name[len-1]=0;
3821 
3822   /* Check name for non-ASCII and convert hostname to ACE form if we can */
3823   if(!is_ASCII_name(host->name)) {
3824 #ifdef USE_LIBIDN
3825     if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
3826       char *ace_hostname = NULL;
3827 
3828       int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
3829       infof(data, "Input domain encoded as `%s'\n",
3830             stringprep_locale_charset());
3831       if(rc == IDNA_SUCCESS) {
3832         /* tld_check_name() displays a warning if the host name contains
3833            "illegal" characters for this TLD */
3834         (void)tld_check_name(data, ace_hostname);
3835 
3836         host->encalloc = ace_hostname;
3837         /* change the name pointer to point to the encoded hostname */
3838         host->name = host->encalloc;
3839       }
3840       else
3841         infof(data, "Failed to convert %s to ACE; %s\n", host->name,
3842               Curl_idn_strerror(conn, rc));
3843     }
3844 #elif defined(USE_WIN32_IDN)
3845     char *ace_hostname = NULL;
3846 
3847     if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
3848       host->encalloc = ace_hostname;
3849       /* change the name pointer to point to the encoded hostname */
3850       host->name = host->encalloc;
3851     }
3852     else
3853       infof(data, "Failed to convert %s to ACE;\n", host->name);
3854 #else
3855     infof(data, "IDN support not present, can't parse Unicode domains\n");
3856 #endif
3857   }
3858 }
3859 
3860 /*
3861  * Frees data allocated by fix_hostname()
3862  */
free_fixed_hostname(struct hostname * host)3863 static void free_fixed_hostname(struct hostname *host)
3864 {
3865 #if defined(USE_LIBIDN)
3866   if(host->encalloc) {
3867     idn_free(host->encalloc); /* must be freed with idn_free() since this was
3868                                  allocated by libidn */
3869     host->encalloc = NULL;
3870   }
3871 #elif defined(USE_WIN32_IDN)
3872   free(host->encalloc); /* must be freed withidn_free() since this was
3873                            allocated by curl_win32_idn_to_ascii */
3874   host->encalloc = NULL;
3875 #else
3876   (void)host;
3877 #endif
3878 }
3879 
llist_dtor(void * user,void * element)3880 static void llist_dtor(void *user, void *element)
3881 {
3882   (void)user;
3883   (void)element;
3884   /* Do nothing */
3885 }
3886 
3887 /*
3888  * Allocate and initialize a new connectdata object.
3889  */
allocate_conn(struct SessionHandle * data)3890 static struct connectdata *allocate_conn(struct SessionHandle *data)
3891 {
3892   struct connectdata *conn = calloc(1, sizeof(struct connectdata));
3893   if(!conn)
3894     return NULL;
3895 
3896   conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined
3897                                            already from start to avoid NULL
3898                                            situations and checks */
3899 
3900   /* and we setup a few fields in case we end up actually using this struct */
3901 
3902   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
3903   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
3904   conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
3905   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
3906   conn->connection_id = -1;    /* no ID */
3907   conn->port = -1; /* unknown at this point */
3908   conn->remote_port = -1; /* unknown */
3909 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
3910   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
3911   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
3912 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
3913 
3914   /* Default protocol-independent behavior doesn't support persistent
3915      connections, so we set this to force-close. Protocols that support
3916      this need to set this to FALSE in their "curl_do" functions. */
3917   connclose(conn, "Default to force-close");
3918 
3919   /* Store creation time to help future close decision making */
3920   conn->created = Curl_tvnow();
3921 
3922   conn->data = data; /* Setup the association between this connection
3923                         and the SessionHandle */
3924 
3925   conn->proxytype = data->set.proxytype; /* type */
3926 
3927 #ifdef CURL_DISABLE_PROXY
3928 
3929   conn->bits.proxy = FALSE;
3930   conn->bits.httpproxy = FALSE;
3931   conn->bits.proxy_user_passwd = FALSE;
3932   conn->bits.tunnel_proxy = FALSE;
3933 
3934 #else /* CURL_DISABLE_PROXY */
3935 
3936   /* note that these two proxy bits are now just on what looks to be
3937      requested, they may be altered down the road */
3938   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
3939                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
3940   conn->bits.httpproxy = (conn->bits.proxy &&
3941                           (conn->proxytype == CURLPROXY_HTTP ||
3942                            conn->proxytype == CURLPROXY_HTTP_1_0)) ?
3943                           TRUE : FALSE;
3944   conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
3945                                  TRUE : FALSE;
3946   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
3947 
3948 #endif /* CURL_DISABLE_PROXY */
3949 
3950   conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
3951   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
3952   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
3953 
3954   conn->verifypeer = data->set.ssl.verifypeer;
3955   conn->verifyhost = data->set.ssl.verifyhost;
3956 
3957   conn->ip_version = data->set.ipver;
3958 
3959 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
3960     defined(NTLM_WB_ENABLED)
3961   conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
3962   conn->ntlm_auth_hlpr_pid = 0;
3963   conn->challenge_header = NULL;
3964   conn->response_header = NULL;
3965 #endif
3966 
3967   if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
3968      !conn->master_buffer) {
3969     /* Allocate master_buffer to be used for HTTP/1 pipelining */
3970     conn->master_buffer = calloc(BUFSIZE, sizeof (char));
3971     if(!conn->master_buffer)
3972       goto error;
3973   }
3974 
3975   /* Initialize the pipeline lists */
3976   conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3977   conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3978   if(!conn->send_pipe || !conn->recv_pipe)
3979     goto error;
3980 
3981 #ifdef HAVE_GSSAPI
3982   conn->data_prot = PROT_CLEAR;
3983 #endif
3984 
3985   /* Store the local bind parameters that will be used for this connection */
3986   if(data->set.str[STRING_DEVICE]) {
3987     conn->localdev = strdup(data->set.str[STRING_DEVICE]);
3988     if(!conn->localdev)
3989       goto error;
3990   }
3991   conn->localportrange = data->set.localportrange;
3992   conn->localport = data->set.localport;
3993 
3994   /* the close socket stuff needs to be copied to the connection struct as
3995      it may live on without (this specific) SessionHandle */
3996   conn->fclosesocket = data->set.fclosesocket;
3997   conn->closesocket_client = data->set.closesocket_client;
3998 
3999   return conn;
4000   error:
4001 
4002   Curl_llist_destroy(conn->send_pipe, NULL);
4003   Curl_llist_destroy(conn->recv_pipe, NULL);
4004 
4005   conn->send_pipe = NULL;
4006   conn->recv_pipe = NULL;
4007 
4008   free(conn->master_buffer);
4009   free(conn->localdev);
4010   free(conn);
4011   return NULL;
4012 }
4013 
findprotocol(struct SessionHandle * data,struct connectdata * conn,const char * protostr)4014 static CURLcode findprotocol(struct SessionHandle *data,
4015                              struct connectdata *conn,
4016                              const char *protostr)
4017 {
4018   const struct Curl_handler * const *pp;
4019   const struct Curl_handler *p;
4020 
4021   /* Scan protocol handler table and match against 'protostr' to set a few
4022      variables based on the URL. Now that the handler may be changed later
4023      when the protocol specific setup function is called. */
4024   for(pp = protocols; (p = *pp) != NULL; pp++) {
4025     if(Curl_raw_equal(p->scheme, protostr)) {
4026       /* Protocol found in table. Check if allowed */
4027       if(!(data->set.allowed_protocols & p->protocol))
4028         /* nope, get out */
4029         break;
4030 
4031       /* it is allowed for "normal" request, now do an extra check if this is
4032          the result of a redirect */
4033       if(data->state.this_is_a_follow &&
4034          !(data->set.redir_protocols & p->protocol))
4035         /* nope, get out */
4036         break;
4037 
4038       /* Perform setup complement if some. */
4039       conn->handler = conn->given = p;
4040 
4041       /* 'port' and 'remote_port' are set in setup_connection_internals() */
4042       return CURLE_OK;
4043     }
4044   }
4045 
4046 
4047   /* The protocol was not found in the table, but we don't have to assign it
4048      to anything since it is already assigned to a dummy-struct in the
4049      create_conn() function when the connectdata struct is allocated. */
4050   failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
4051         protostr);
4052 
4053   return CURLE_UNSUPPORTED_PROTOCOL;
4054 }
4055 
4056 /*
4057  * Parse URL and fill in the relevant members of the connection struct.
4058  */
parseurlandfillconn(struct SessionHandle * data,struct connectdata * conn,bool * prot_missing,char ** userp,char ** passwdp,char ** optionsp)4059 static CURLcode parseurlandfillconn(struct SessionHandle *data,
4060                                     struct connectdata *conn,
4061                                     bool *prot_missing,
4062                                     char **userp, char **passwdp,
4063                                     char **optionsp)
4064 {
4065   char *at;
4066   char *fragment;
4067   char *path = data->state.path;
4068   char *query;
4069   int rc;
4070   char protobuf[16] = "";
4071   const char *protop = "";
4072   CURLcode result;
4073   bool rebuild_url = FALSE;
4074 
4075   *prot_missing = FALSE;
4076 
4077   /* We might pass the entire URL into the request so we need to make sure
4078    * there are no bad characters in there.*/
4079   if(strpbrk(data->change.url, "\r\n")) {
4080     failf(data, "Illegal characters found in URL");
4081     return CURLE_URL_MALFORMAT;
4082   }
4083 
4084   /*************************************************************
4085    * Parse the URL.
4086    *
4087    * We need to parse the url even when using the proxy, because we will need
4088    * the hostname and port in case we are trying to SSL connect through the
4089    * proxy -- and we don't know if we will need to use SSL until we parse the
4090    * url ...
4091    ************************************************************/
4092   if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
4093                   protobuf, path)) &&
4094      Curl_raw_equal(protobuf, "file")) {
4095     if(path[0] == '/' && path[1] == '/') {
4096       /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
4097        * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
4098        * file://localhost/<path> is similar to how other schemes treat missing
4099        * hostnames.  See RFC 1808. */
4100 
4101       /* This cannot be done with strcpy() in a portable manner, since the
4102          memory areas overlap! */
4103       memmove(path, path + 2, strlen(path + 2)+1);
4104     }
4105     /*
4106      * we deal with file://<host>/<path> differently since it supports no
4107      * hostname other than "localhost" and "127.0.0.1", which is unique among
4108      * the URL protocols specified in RFC 1738
4109      */
4110     if(path[0] != '/') {
4111       /* the URL included a host name, we ignore host names in file:// URLs
4112          as the standards don't define what to do with them */
4113       char *ptr=strchr(path, '/');
4114       if(ptr) {
4115         /* there was a slash present
4116 
4117            RFC1738 (section 3.1, page 5) says:
4118 
4119            The rest of the locator consists of data specific to the scheme,
4120            and is known as the "url-path". It supplies the details of how the
4121            specified resource can be accessed. Note that the "/" between the
4122            host (or port) and the url-path is NOT part of the url-path.
4123 
4124            As most agents use file://localhost/foo to get '/foo' although the
4125            slash preceding foo is a separator and not a slash for the path,
4126            a URL as file://localhost//foo must be valid as well, to refer to
4127            the same file with an absolute path.
4128         */
4129 
4130         if(ptr[1] && ('/' == ptr[1]))
4131           /* if there was two slashes, we skip the first one as that is then
4132              used truly as a separator */
4133           ptr++;
4134 
4135         /* This cannot be made with strcpy, as the memory chunks overlap! */
4136         memmove(path, ptr, strlen(ptr)+1);
4137       }
4138     }
4139 
4140     protop = "file"; /* protocol string */
4141   }
4142   else {
4143     /* clear path */
4144     path[0]=0;
4145 
4146     if(2 > sscanf(data->change.url,
4147                    "%15[^\n:]://%[^\n/?]%[^\n]",
4148                    protobuf,
4149                    conn->host.name, path)) {
4150 
4151       /*
4152        * The URL was badly formatted, let's try the browser-style _without_
4153        * protocol specified like 'http://'.
4154        */
4155       rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
4156       if(1 > rc) {
4157         /*
4158          * We couldn't even get this format.
4159          * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
4160          * assigned, but the return value is EOF!
4161          */
4162 #if defined(__DJGPP__) && (DJGPP_MINOR == 4)
4163         if(!(rc == -1 && *conn->host.name))
4164 #endif
4165         {
4166           failf(data, "<url> malformed");
4167           return CURLE_URL_MALFORMAT;
4168         }
4169       }
4170 
4171       /*
4172        * Since there was no protocol part specified in the URL use the
4173        * user-specified default protocol. If we weren't given a default make a
4174        * guess by matching some protocols against the host's outermost
4175        * sub-domain name. Finally if there was no match use HTTP.
4176        */
4177 
4178       protop = data->set.str[STRING_DEFAULT_PROTOCOL];
4179       if(!protop) {
4180         /* Note: if you add a new protocol, please update the list in
4181          * lib/version.c too! */
4182         if(checkprefix("FTP.", conn->host.name))
4183           protop = "ftp";
4184         else if(checkprefix("DICT.", conn->host.name))
4185           protop = "DICT";
4186         else if(checkprefix("LDAP.", conn->host.name))
4187           protop = "LDAP";
4188         else if(checkprefix("IMAP.", conn->host.name))
4189           protop = "IMAP";
4190         else if(checkprefix("SMTP.", conn->host.name))
4191           protop = "smtp";
4192         else if(checkprefix("POP3.", conn->host.name))
4193           protop = "pop3";
4194         else
4195           protop = "http";
4196       }
4197 
4198       *prot_missing = TRUE; /* not given in URL */
4199     }
4200     else
4201       protop = protobuf;
4202   }
4203 
4204   /* We search for '?' in the host name (but only on the right side of a
4205    * @-letter to allow ?-letters in username and password) to handle things
4206    * like http://example.com?param= (notice the missing '/').
4207    */
4208   at = strchr(conn->host.name, '@');
4209   if(at)
4210     query = strchr(at+1, '?');
4211   else
4212     query = strchr(conn->host.name, '?');
4213 
4214   if(query) {
4215     /* We must insert a slash before the '?'-letter in the URL. If the URL had
4216        a slash after the '?', that is where the path currently begins and the
4217        '?string' is still part of the host name.
4218 
4219        We must move the trailing part from the host name and put it first in
4220        the path. And have it all prefixed with a slash.
4221     */
4222 
4223     size_t hostlen = strlen(query);
4224     size_t pathlen = strlen(path);
4225 
4226     /* move the existing path plus the zero byte forward, to make room for
4227        the host-name part */
4228     memmove(path+hostlen+1, path, pathlen+1);
4229 
4230      /* now copy the trailing host part in front of the existing path */
4231     memcpy(path+1, query, hostlen);
4232 
4233     path[0]='/'; /* prepend the missing slash */
4234     rebuild_url = TRUE;
4235 
4236     *query=0; /* now cut off the hostname at the ? */
4237   }
4238   else if(!path[0]) {
4239     /* if there's no path set, use a single slash */
4240     strcpy(path, "/");
4241     rebuild_url = TRUE;
4242   }
4243 
4244   /* If the URL is malformatted (missing a '/' after hostname before path) we
4245    * insert a slash here. The only letter except '/' we accept to start a path
4246    * is '?'.
4247    */
4248   if(path[0] == '?') {
4249     /* We need this function to deal with overlapping memory areas. We know
4250        that the memory area 'path' points to is 'urllen' bytes big and that
4251        is bigger than the path. Use +1 to move the zero byte too. */
4252     memmove(&path[1], path, strlen(path)+1);
4253     path[0] = '/';
4254     rebuild_url = TRUE;
4255   }
4256   else if(!data->set.path_as_is) {
4257     /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
4258     char *newp = Curl_dedotdotify(path);
4259     if(!newp)
4260       return CURLE_OUT_OF_MEMORY;
4261 
4262     if(strcmp(newp, path)) {
4263       rebuild_url = TRUE;
4264       free(data->state.pathbuffer);
4265       data->state.pathbuffer = newp;
4266       data->state.path = newp;
4267       path = newp;
4268     }
4269     else
4270       free(newp);
4271   }
4272 
4273   /*
4274    * "rebuild_url" means that one or more URL components have been modified so
4275    * we need to generate an updated full version.  We need the corrected URL
4276    * when communicating over HTTP proxy and we don't know at this point if
4277    * we're using a proxy or not.
4278    */
4279   if(rebuild_url) {
4280     char *reurl;
4281 
4282     size_t plen = strlen(path); /* new path, should be 1 byte longer than
4283                                    the original */
4284     size_t urllen = strlen(data->change.url); /* original URL length */
4285 
4286     size_t prefixlen = strlen(conn->host.name);
4287 
4288     if(!*prot_missing)
4289       prefixlen += strlen(protop) + strlen("://");
4290 
4291     reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
4292     if(!reurl)
4293       return CURLE_OUT_OF_MEMORY;
4294 
4295     /* copy the prefix */
4296     memcpy(reurl, data->change.url, prefixlen);
4297 
4298     /* append the trailing piece + zerobyte */
4299     memcpy(&reurl[prefixlen], path, plen + 1);
4300 
4301     /* possible free the old one */
4302     if(data->change.url_alloc) {
4303       Curl_safefree(data->change.url);
4304       data->change.url_alloc = FALSE;
4305     }
4306 
4307     infof(data, "Rebuilt URL to: %s\n", reurl);
4308 
4309     data->change.url = reurl;
4310     data->change.url_alloc = TRUE; /* free this later */
4311   }
4312 
4313   /*
4314    * Parse the login details from the URL and strip them out of
4315    * the host name
4316    */
4317   result = parse_url_login(data, conn, userp, passwdp, optionsp);
4318   if(result)
4319     return result;
4320 
4321   if(conn->host.name[0] == '[') {
4322     /* This looks like an IPv6 address literal.  See if there is an address
4323        scope if there is no location header */
4324     char *percent = strchr(conn->host.name, '%');
4325     if(percent) {
4326       unsigned int identifier_offset = 3;
4327       char *endp;
4328       unsigned long scope;
4329       if(strncmp("%25", percent, 3) != 0) {
4330         infof(data,
4331               "Please URL encode %% as %%25, see RFC 6874.\n");
4332         identifier_offset = 1;
4333       }
4334       scope = strtoul(percent + identifier_offset, &endp, 10);
4335       if(*endp == ']') {
4336         /* The address scope was well formed.  Knock it out of the
4337            hostname. */
4338         memmove(percent, endp, strlen(endp)+1);
4339         conn->scope_id = (unsigned int)scope;
4340       }
4341       else {
4342         /* Zone identifier is not numeric */
4343 #if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
4344         char ifname[IFNAMSIZ + 2];
4345         char *square_bracket;
4346         unsigned int scopeidx = 0;
4347         strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
4348         /* Ensure nullbyte termination */
4349         ifname[IFNAMSIZ + 1] = '\0';
4350         square_bracket = strchr(ifname, ']');
4351         if(square_bracket) {
4352           /* Remove ']' */
4353           *square_bracket = '\0';
4354           scopeidx = if_nametoindex(ifname);
4355           if(scopeidx == 0) {
4356             infof(data, "Invalid network interface: %s; %s\n", ifname,
4357                   strerror(errno));
4358           }
4359         }
4360         if(scopeidx > 0) {
4361           char *p = percent + identifier_offset + strlen(ifname);
4362 
4363           /* Remove zone identifier from hostname */
4364           memmove(percent, p, strlen(p) + 1);
4365           conn->scope_id = scopeidx;
4366         }
4367         else
4368 #endif /* HAVE_NET_IF_H && IFNAMSIZ */
4369           infof(data, "Invalid IPv6 address format\n");
4370       }
4371     }
4372   }
4373 
4374   if(data->set.scope_id)
4375     /* Override any scope that was set above.  */
4376     conn->scope_id = data->set.scope_id;
4377 
4378   /* Remove the fragment part of the path. Per RFC 2396, this is always the
4379      last part of the URI. We are looking for the first '#' so that we deal
4380      gracefully with non conformant URI such as http://example.com#foo#bar. */
4381   fragment = strchr(path, '#');
4382   if(fragment) {
4383     *fragment = 0;
4384 
4385     /* we know the path part ended with a fragment, so we know the full URL
4386        string does too and we need to cut it off from there so it isn't used
4387        over proxy */
4388     fragment = strchr(data->change.url, '#');
4389     if(fragment)
4390       *fragment = 0;
4391   }
4392 
4393   /*
4394    * So if the URL was A://B/C#D,
4395    *   protop is A
4396    *   conn->host.name is B
4397    *   data->state.path is /C
4398    */
4399 
4400   return findprotocol(data, conn, protop);
4401 }
4402 
4403 /*
4404  * If we're doing a resumed transfer, we need to setup our stuff
4405  * properly.
4406  */
setup_range(struct SessionHandle * data)4407 static CURLcode setup_range(struct SessionHandle *data)
4408 {
4409   struct UrlState *s = &data->state;
4410   s->resume_from = data->set.set_resume_from;
4411   if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
4412     if(s->rangestringalloc)
4413       free(s->range);
4414 
4415     if(s->resume_from)
4416       s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
4417     else
4418       s->range = strdup(data->set.str[STRING_SET_RANGE]);
4419 
4420     s->rangestringalloc = (s->range) ? TRUE : FALSE;
4421 
4422     if(!s->range)
4423       return CURLE_OUT_OF_MEMORY;
4424 
4425     /* tell ourselves to fetch this range */
4426     s->use_range = TRUE;        /* enable range download */
4427   }
4428   else
4429     s->use_range = FALSE; /* disable range download */
4430 
4431   return CURLE_OK;
4432 }
4433 
4434 
4435 /*
4436  * setup_connection_internals() -
4437  *
4438  * Setup connection internals specific to the requested protocol in the
4439  * SessionHandle. This is inited and setup before the connection is made but
4440  * is about the particular protocol that is to be used.
4441  *
4442  * This MUST get called after proxy magic has been figured out.
4443  */
setup_connection_internals(struct connectdata * conn)4444 static CURLcode setup_connection_internals(struct connectdata *conn)
4445 {
4446   const struct Curl_handler * p;
4447   CURLcode result;
4448   struct SessionHandle *data = conn->data;
4449 
4450   /* in some case in the multi state-machine, we go back to the CONNECT state
4451      and then a second (or third or...) call to this function will be made
4452      without doing a DISCONNECT or DONE in between (since the connection is
4453      yet in place) and therefore this function needs to first make sure
4454      there's no lingering previous data allocated. */
4455   Curl_free_request_state(data);
4456 
4457   memset(&data->req, 0, sizeof(struct SingleRequest));
4458   data->req.maxdownload = -1;
4459 
4460   conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
4461 
4462   /* Perform setup complement if some. */
4463   p = conn->handler;
4464 
4465   if(p->setup_connection) {
4466     result = (*p->setup_connection)(conn);
4467 
4468     if(result)
4469       return result;
4470 
4471     p = conn->handler;              /* May have changed. */
4472   }
4473 
4474   if(conn->port < 0)
4475     /* we check for -1 here since if proxy was detected already, this
4476        was very likely already set to the proxy port */
4477     conn->port = p->defport;
4478 
4479   return CURLE_OK;
4480 }
4481 
4482 /*
4483  * Curl_free_request_state() should free temp data that was allocated in the
4484  * SessionHandle for this single request.
4485  */
4486 
Curl_free_request_state(struct SessionHandle * data)4487 void Curl_free_request_state(struct SessionHandle *data)
4488 {
4489   Curl_safefree(data->req.protop);
4490   Curl_safefree(data->req.newurl);
4491 }
4492 
4493 
4494 #ifndef CURL_DISABLE_PROXY
4495 /****************************************************************
4496 * Checks if the host is in the noproxy list. returns true if it matches
4497 * and therefore the proxy should NOT be used.
4498 ****************************************************************/
check_noproxy(const char * name,const char * no_proxy)4499 static bool check_noproxy(const char* name, const char* no_proxy)
4500 {
4501   /* no_proxy=domain1.dom,host.domain2.dom
4502    *   (a comma-separated list of hosts which should
4503    *   not be proxied, or an asterisk to override
4504    *   all proxy variables)
4505    */
4506   size_t tok_start;
4507   size_t tok_end;
4508   const char* separator = ", ";
4509   size_t no_proxy_len;
4510   size_t namelen;
4511   char *endptr;
4512 
4513   if(no_proxy && no_proxy[0]) {
4514     if(Curl_raw_equal("*", no_proxy)) {
4515       return TRUE;
4516     }
4517 
4518     /* NO_PROXY was specified and it wasn't just an asterisk */
4519 
4520     no_proxy_len = strlen(no_proxy);
4521     endptr = strchr(name, ':');
4522     if(endptr)
4523       namelen = endptr - name;
4524     else
4525       namelen = strlen(name);
4526 
4527     for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
4528       while(tok_start < no_proxy_len &&
4529             strchr(separator, no_proxy[tok_start]) != NULL) {
4530         /* Look for the beginning of the token. */
4531         ++tok_start;
4532       }
4533 
4534       if(tok_start == no_proxy_len)
4535         break; /* It was all trailing separator chars, no more tokens. */
4536 
4537       for(tok_end = tok_start; tok_end < no_proxy_len &&
4538             strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
4539         /* Look for the end of the token. */
4540         ;
4541 
4542       /* To match previous behaviour, where it was necessary to specify
4543        * ".local.com" to prevent matching "notlocal.com", we will leave
4544        * the '.' off.
4545        */
4546       if(no_proxy[tok_start] == '.')
4547         ++tok_start;
4548 
4549       if((tok_end - tok_start) <= namelen) {
4550         /* Match the last part of the name to the domain we are checking. */
4551         const char *checkn = name + namelen - (tok_end - tok_start);
4552         if(Curl_raw_nequal(no_proxy + tok_start, checkn,
4553                            tok_end - tok_start)) {
4554           if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
4555             /* We either have an exact match, or the previous character is a .
4556              * so it is within the same domain, so no proxy for this host.
4557              */
4558             return TRUE;
4559           }
4560         }
4561       } /* if((tok_end - tok_start) <= namelen) */
4562     } /* for(tok_start = 0; tok_start < no_proxy_len;
4563          tok_start = tok_end + 1) */
4564   } /* NO_PROXY was specified and it wasn't just an asterisk */
4565 
4566   return FALSE;
4567 }
4568 
4569 /****************************************************************
4570 * Detect what (if any) proxy to use. Remember that this selects a host
4571 * name and is not limited to HTTP proxies only.
4572 * The returned pointer must be freed by the caller (unless NULL)
4573 ****************************************************************/
detect_proxy(struct connectdata * conn)4574 static char *detect_proxy(struct connectdata *conn)
4575 {
4576   char *proxy = NULL;
4577 
4578 #ifndef CURL_DISABLE_HTTP
4579   /* If proxy was not specified, we check for default proxy environment
4580    * variables, to enable i.e Lynx compliance:
4581    *
4582    * http_proxy=http://some.server.dom:port/
4583    * https_proxy=http://some.server.dom:port/
4584    * ftp_proxy=http://some.server.dom:port/
4585    * no_proxy=domain1.dom,host.domain2.dom
4586    *   (a comma-separated list of hosts which should
4587    *   not be proxied, or an asterisk to override
4588    *   all proxy variables)
4589    * all_proxy=http://some.server.dom:port/
4590    *   (seems to exist for the CERN www lib. Probably
4591    *   the first to check for.)
4592    *
4593    * For compatibility, the all-uppercase versions of these variables are
4594    * checked if the lowercase versions don't exist.
4595    */
4596   char *no_proxy=NULL;
4597   char proxy_env[128];
4598 
4599   no_proxy=curl_getenv("no_proxy");
4600   if(!no_proxy)
4601     no_proxy=curl_getenv("NO_PROXY");
4602 
4603   if(!check_noproxy(conn->host.name, no_proxy)) {
4604     /* It was not listed as without proxy */
4605     const char *protop = conn->handler->scheme;
4606     char *envp = proxy_env;
4607     char *prox;
4608 
4609     /* Now, build <protocol>_proxy and check for such a one to use */
4610     while(*protop)
4611       *envp++ = (char)tolower((int)*protop++);
4612 
4613     /* append _proxy */
4614     strcpy(envp, "_proxy");
4615 
4616     /* read the protocol proxy: */
4617     prox=curl_getenv(proxy_env);
4618 
4619     /*
4620      * We don't try the uppercase version of HTTP_PROXY because of
4621      * security reasons:
4622      *
4623      * When curl is used in a webserver application
4624      * environment (cgi or php), this environment variable can
4625      * be controlled by the web server user by setting the
4626      * http header 'Proxy:' to some value.
4627      *
4628      * This can cause 'internal' http/ftp requests to be
4629      * arbitrarily redirected by any external attacker.
4630      */
4631     if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
4632       /* There was no lowercase variable, try the uppercase version: */
4633       Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
4634       prox=curl_getenv(proxy_env);
4635     }
4636 
4637     if(prox)
4638       proxy = prox; /* use this */
4639     else {
4640       proxy = curl_getenv("all_proxy"); /* default proxy to use */
4641       if(!proxy)
4642         proxy=curl_getenv("ALL_PROXY");
4643     }
4644   } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
4645        non-proxy */
4646   free(no_proxy);
4647 
4648 #else /* !CURL_DISABLE_HTTP */
4649 
4650   (void)conn;
4651 #endif /* CURL_DISABLE_HTTP */
4652 
4653   return proxy;
4654 }
4655 
4656 /*
4657  * If this is supposed to use a proxy, we need to figure out the proxy
4658  * host name, so that we can re-use an existing connection
4659  * that may exist registered to the same proxy host.
4660  */
parse_proxy(struct SessionHandle * data,struct connectdata * conn,char * proxy)4661 static CURLcode parse_proxy(struct SessionHandle *data,
4662                             struct connectdata *conn, char *proxy)
4663 {
4664   char *prox_portno;
4665   char *endofprot;
4666 
4667   /* We use 'proxyptr' to point to the proxy name from now on... */
4668   char *proxyptr;
4669   char *portptr;
4670   char *atsign;
4671 
4672   /* We do the proxy host string parsing here. We want the host name and the
4673    * port name. Accept a protocol:// prefix
4674    */
4675 
4676   /* Parse the protocol part if present */
4677   endofprot = strstr(proxy, "://");
4678   if(endofprot) {
4679     proxyptr = endofprot+3;
4680     if(checkprefix("socks5h", proxy))
4681       conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
4682     else if(checkprefix("socks5", proxy))
4683       conn->proxytype = CURLPROXY_SOCKS5;
4684     else if(checkprefix("socks4a", proxy))
4685       conn->proxytype = CURLPROXY_SOCKS4A;
4686     else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
4687       conn->proxytype = CURLPROXY_SOCKS4;
4688     /* Any other xxx:// : change to http proxy */
4689   }
4690   else
4691     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
4692 
4693   /* Is there a username and password given in this proxy url? */
4694   atsign = strchr(proxyptr, '@');
4695   if(atsign) {
4696     char *proxyuser = NULL;
4697     char *proxypasswd = NULL;
4698     CURLcode result =
4699       parse_login_details(proxyptr, atsign - proxyptr,
4700                           &proxyuser, &proxypasswd, NULL);
4701     if(!result) {
4702       /* found user and password, rip them out.  note that we are
4703          unescaping them, as there is otherwise no way to have a
4704          username or password with reserved characters like ':' in
4705          them. */
4706       Curl_safefree(conn->proxyuser);
4707       if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
4708         conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
4709       else
4710         conn->proxyuser = strdup("");
4711 
4712       if(!conn->proxyuser)
4713         result = CURLE_OUT_OF_MEMORY;
4714       else {
4715         Curl_safefree(conn->proxypasswd);
4716         if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
4717           conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
4718         else
4719           conn->proxypasswd = strdup("");
4720 
4721         if(!conn->proxypasswd)
4722           result = CURLE_OUT_OF_MEMORY;
4723       }
4724 
4725       if(!result) {
4726         conn->bits.proxy_user_passwd = TRUE; /* enable it */
4727         atsign++; /* the right side of the @-letter */
4728 
4729         proxyptr = atsign; /* now use this instead */
4730       }
4731     }
4732 
4733     free(proxyuser);
4734     free(proxypasswd);
4735 
4736     if(result)
4737       return result;
4738   }
4739 
4740   /* start scanning for port number at this point */
4741   portptr = proxyptr;
4742 
4743   /* detect and extract RFC6874-style IPv6-addresses */
4744   if(*proxyptr == '[') {
4745     char *ptr = ++proxyptr; /* advance beyond the initial bracket */
4746     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
4747       ptr++;
4748     if(*ptr == '%') {
4749       /* There might be a zone identifier */
4750       if(strncmp("%25", ptr, 3))
4751         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
4752       ptr++;
4753       /* Allow unreserved characters as defined in RFC 3986 */
4754       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
4755                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
4756         ptr++;
4757     }
4758     if(*ptr == ']')
4759       /* yeps, it ended nicely with a bracket as well */
4760       *ptr++ = 0;
4761     else
4762       infof(data, "Invalid IPv6 address format\n");
4763     portptr = ptr;
4764     /* Note that if this didn't end with a bracket, we still advanced the
4765      * proxyptr first, but I can't see anything wrong with that as no host
4766      * name nor a numeric can legally start with a bracket.
4767      */
4768   }
4769 
4770   /* Get port number off proxy.server.com:1080 */
4771   prox_portno = strchr(portptr, ':');
4772   if(prox_portno) {
4773     char *endp = NULL;
4774     long port = 0;
4775     *prox_portno = 0x0; /* cut off number from host name */
4776     prox_portno ++;
4777     /* now set the local port number */
4778     port = strtol(prox_portno, &endp, 10);
4779     if((endp && *endp && (*endp != '/') && (*endp != ' ')) ||
4780        (port < 0) || (port > 65535)) {
4781       /* meant to detect for example invalid IPv6 numerical addresses without
4782          brackets: "2a00:fac0:a000::7:13". Accept a trailing slash only
4783          because we then allow "URL style" with the number followed by a
4784          slash, used in curl test cases already. Space is also an acceptable
4785          terminating symbol. */
4786       infof(data, "No valid port number in proxy string (%s)\n",
4787             prox_portno);
4788     }
4789     else
4790       conn->port = port;
4791   }
4792   else {
4793     if(proxyptr[0]=='/')
4794       /* If the first character in the proxy string is a slash, fail
4795          immediately. The following code will otherwise clear the string which
4796          will lead to code running as if no proxy was set! */
4797       return CURLE_COULDNT_RESOLVE_PROXY;
4798 
4799     /* without a port number after the host name, some people seem to use
4800        a slash so we strip everything from the first slash */
4801     atsign = strchr(proxyptr, '/');
4802     if(atsign)
4803       *atsign = '\0'; /* cut off path part from host name */
4804 
4805     if(data->set.proxyport)
4806       /* None given in the proxy string, then get the default one if it is
4807          given */
4808       conn->port = data->set.proxyport;
4809   }
4810 
4811   /* now, clone the cleaned proxy host name */
4812   conn->proxy.rawalloc = strdup(proxyptr);
4813   conn->proxy.name = conn->proxy.rawalloc;
4814 
4815   if(!conn->proxy.rawalloc)
4816     return CURLE_OUT_OF_MEMORY;
4817 
4818   return CURLE_OK;
4819 }
4820 
4821 /*
4822  * Extract the user and password from the authentication string
4823  */
parse_proxy_auth(struct SessionHandle * data,struct connectdata * conn)4824 static CURLcode parse_proxy_auth(struct SessionHandle *data,
4825                                  struct connectdata *conn)
4826 {
4827   char proxyuser[MAX_CURL_USER_LENGTH]="";
4828   char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
4829 
4830   if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
4831     strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
4832             MAX_CURL_USER_LENGTH);
4833     proxyuser[MAX_CURL_USER_LENGTH-1] = '\0';   /*To be on safe side*/
4834   }
4835   if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
4836     strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
4837             MAX_CURL_PASSWORD_LENGTH);
4838     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
4839   }
4840 
4841   conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
4842   if(!conn->proxyuser)
4843     return CURLE_OUT_OF_MEMORY;
4844 
4845   conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
4846   if(!conn->proxypasswd)
4847     return CURLE_OUT_OF_MEMORY;
4848 
4849   return CURLE_OK;
4850 }
4851 #endif /* CURL_DISABLE_PROXY */
4852 
4853 /*
4854  * parse_url_login()
4855  *
4856  * Parse the login details (user name, password and options) from the URL and
4857  * strip them out of the host name
4858  *
4859  * Inputs: data->set.use_netrc (CURLOPT_NETRC)
4860  *         conn->host.name
4861  *
4862  * Outputs: (almost :- all currently undefined)
4863  *          conn->bits.user_passwd  - non-zero if non-default passwords exist
4864  *          user                    - non-zero length if defined
4865  *          passwd                  - non-zero length if defined
4866  *          options                 - non-zero length if defined
4867  *          conn->host.name         - remove user name and password
4868  */
parse_url_login(struct SessionHandle * data,struct connectdata * conn,char ** user,char ** passwd,char ** options)4869 static CURLcode parse_url_login(struct SessionHandle *data,
4870                                 struct connectdata *conn,
4871                                 char **user, char **passwd, char **options)
4872 {
4873   CURLcode result = CURLE_OK;
4874   char *userp = NULL;
4875   char *passwdp = NULL;
4876   char *optionsp = NULL;
4877 
4878   /* At this point, we're hoping all the other special cases have
4879    * been taken care of, so conn->host.name is at most
4880    *    [user[:password][;options]]@]hostname
4881    *
4882    * We need somewhere to put the embedded details, so do that first.
4883    */
4884 
4885   char *ptr = strchr(conn->host.name, '@');
4886   char *login = conn->host.name;
4887 
4888   DEBUGASSERT(!**user);
4889   DEBUGASSERT(!**passwd);
4890   DEBUGASSERT(!**options);
4891 
4892   if(!ptr)
4893     goto out;
4894 
4895   /* We will now try to extract the
4896    * possible login information in a string like:
4897    * ftp://user:password@ftp.my.site:8021/README */
4898   conn->host.name = ++ptr;
4899 
4900   /* So the hostname is sane.  Only bother interpreting the
4901    * results if we could care.  It could still be wasted
4902    * work because it might be overtaken by the programmatically
4903    * set user/passwd, but doing that first adds more cases here :-(
4904    */
4905 
4906   if(data->set.use_netrc == CURL_NETRC_REQUIRED)
4907     goto out;
4908 
4909   /* We could use the login information in the URL so extract it */
4910   result = parse_login_details(login, ptr - login - 1,
4911                                &userp, &passwdp, &optionsp);
4912   if(result)
4913     goto out;
4914 
4915   if(userp) {
4916     char *newname;
4917 
4918     /* We have a user in the URL */
4919     conn->bits.userpwd_in_url = TRUE;
4920     conn->bits.user_passwd = TRUE; /* enable user+password */
4921 
4922     /* Decode the user */
4923     newname = curl_easy_unescape(data, userp, 0, NULL);
4924     if(!newname) {
4925       result = CURLE_OUT_OF_MEMORY;
4926       goto out;
4927     }
4928 
4929     free(*user);
4930     *user = newname;
4931   }
4932 
4933   if(passwdp) {
4934     /* We have a password in the URL so decode it */
4935     char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
4936     if(!newpasswd) {
4937       result = CURLE_OUT_OF_MEMORY;
4938       goto out;
4939     }
4940 
4941     free(*passwd);
4942     *passwd = newpasswd;
4943   }
4944 
4945   if(optionsp) {
4946     /* We have an options list in the URL so decode it */
4947     char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
4948     if(!newoptions) {
4949       result = CURLE_OUT_OF_MEMORY;
4950       goto out;
4951     }
4952 
4953     free(*options);
4954     *options = newoptions;
4955   }
4956 
4957 
4958   out:
4959 
4960   free(userp);
4961   free(passwdp);
4962   free(optionsp);
4963 
4964   return result;
4965 }
4966 
4967 /*
4968  * parse_login_details()
4969  *
4970  * This is used to parse a login string for user name, password and options in
4971  * the following formats:
4972  *
4973  *   user
4974  *   user:password
4975  *   user:password;options
4976  *   user;options
4977  *   user;options:password
4978  *   :password
4979  *   :password;options
4980  *   ;options
4981  *   ;options:password
4982  *
4983  * Parameters:
4984  *
4985  * login    [in]     - The login string.
4986  * len      [in]     - The length of the login string.
4987  * userp    [in/out] - The address where a pointer to newly allocated memory
4988  *                     holding the user will be stored upon completion.
4989  * passdwp  [in/out] - The address where a pointer to newly allocated memory
4990  *                     holding the password will be stored upon completion.
4991  * optionsp [in/out] - The address where a pointer to newly allocated memory
4992  *                     holding the options will be stored upon completion.
4993  *
4994  * Returns CURLE_OK on success.
4995  */
parse_login_details(const char * login,const size_t len,char ** userp,char ** passwdp,char ** optionsp)4996 static CURLcode parse_login_details(const char *login, const size_t len,
4997                                     char **userp, char **passwdp,
4998                                     char **optionsp)
4999 {
5000   CURLcode result = CURLE_OK;
5001   char *ubuf = NULL;
5002   char *pbuf = NULL;
5003   char *obuf = NULL;
5004   const char *psep = NULL;
5005   const char *osep = NULL;
5006   size_t ulen;
5007   size_t plen;
5008   size_t olen;
5009 
5010   /* Attempt to find the password separator */
5011   if(passwdp) {
5012     psep = strchr(login, ':');
5013 
5014     /* Within the constraint of the login string */
5015     if(psep >= login + len)
5016       psep = NULL;
5017   }
5018 
5019   /* Attempt to find the options separator */
5020   if(optionsp) {
5021     osep = strchr(login, ';');
5022 
5023     /* Within the constraint of the login string */
5024     if(osep >= login + len)
5025       osep = NULL;
5026   }
5027 
5028   /* Calculate the portion lengths */
5029   ulen = (psep ?
5030           (size_t)(osep && psep > osep ? osep - login : psep - login) :
5031           (osep ? (size_t)(osep - login) : len));
5032   plen = (psep ?
5033           (osep && osep > psep ? (size_t)(osep - psep) :
5034                                  (size_t)(login + len - psep)) - 1 : 0);
5035   olen = (osep ?
5036           (psep && psep > osep ? (size_t)(psep - osep) :
5037                                  (size_t)(login + len - osep)) - 1 : 0);
5038 
5039   /* Allocate the user portion buffer */
5040   if(userp && ulen) {
5041     ubuf = malloc(ulen + 1);
5042     if(!ubuf)
5043       result = CURLE_OUT_OF_MEMORY;
5044   }
5045 
5046   /* Allocate the password portion buffer */
5047   if(!result && passwdp && plen) {
5048     pbuf = malloc(plen + 1);
5049     if(!pbuf) {
5050       free(ubuf);
5051       result = CURLE_OUT_OF_MEMORY;
5052     }
5053   }
5054 
5055   /* Allocate the options portion buffer */
5056   if(!result && optionsp && olen) {
5057     obuf = malloc(olen + 1);
5058     if(!obuf) {
5059       free(pbuf);
5060       free(ubuf);
5061       result = CURLE_OUT_OF_MEMORY;
5062     }
5063   }
5064 
5065   if(!result) {
5066     /* Store the user portion if necessary */
5067     if(ubuf) {
5068       memcpy(ubuf, login, ulen);
5069       ubuf[ulen] = '\0';
5070       Curl_safefree(*userp);
5071       *userp = ubuf;
5072     }
5073 
5074     /* Store the password portion if necessary */
5075     if(pbuf) {
5076       memcpy(pbuf, psep + 1, plen);
5077       pbuf[plen] = '\0';
5078       Curl_safefree(*passwdp);
5079       *passwdp = pbuf;
5080     }
5081 
5082     /* Store the options portion if necessary */
5083     if(obuf) {
5084       memcpy(obuf, osep + 1, olen);
5085       obuf[olen] = '\0';
5086       Curl_safefree(*optionsp);
5087       *optionsp = obuf;
5088     }
5089   }
5090 
5091   return result;
5092 }
5093 
5094 /*************************************************************
5095  * Figure out the remote port number and fix it in the URL
5096  *
5097  * No matter if we use a proxy or not, we have to figure out the remote
5098  * port number of various reasons.
5099  *
5100  * To be able to detect port number flawlessly, we must not confuse them
5101  * IPv6-specified addresses in the [0::1] style. (RFC2732)
5102  *
5103  * The conn->host.name is currently [user:passwd@]host[:port] where host
5104  * could be a hostname, IPv4 address or IPv6 address.
5105  *
5106  * The port number embedded in the URL is replaced, if necessary.
5107  *************************************************************/
parse_remote_port(struct SessionHandle * data,struct connectdata * conn)5108 static CURLcode parse_remote_port(struct SessionHandle *data,
5109                                   struct connectdata *conn)
5110 {
5111   char *portptr;
5112   char endbracket;
5113 
5114   /* Note that at this point, the IPv6 address cannot contain any scope
5115      suffix as that has already been removed in the parseurlandfillconn()
5116      function */
5117   if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
5118                   &endbracket)) &&
5119      (']' == endbracket)) {
5120     /* this is a RFC2732-style specified IP-address */
5121     conn->bits.ipv6_ip = TRUE;
5122 
5123     conn->host.name++; /* skip over the starting bracket */
5124     portptr = strchr(conn->host.name, ']');
5125     if(portptr) {
5126       *portptr++ = '\0'; /* zero terminate, killing the bracket */
5127       if(':' != *portptr)
5128         portptr = NULL; /* no port number available */
5129     }
5130   }
5131   else {
5132 #ifdef ENABLE_IPV6
5133     struct in6_addr in6;
5134     if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
5135       /* This is a numerical IPv6 address, meaning this is a wrongly formatted
5136          URL */
5137       failf(data, "IPv6 numerical address used in URL without brackets");
5138       return CURLE_URL_MALFORMAT;
5139     }
5140 #endif
5141 
5142     portptr = strrchr(conn->host.name, ':');
5143   }
5144 
5145   if(data->set.use_port && data->state.allow_port) {
5146     /* if set, we use this and ignore the port possibly given in the URL */
5147     conn->remote_port = (unsigned short)data->set.use_port;
5148     if(portptr)
5149       *portptr = '\0'; /* cut off the name there anyway - if there was a port
5150                       number - since the port number is to be ignored! */
5151     if(conn->bits.httpproxy) {
5152       /* we need to create new URL with the new port number */
5153       char *url;
5154       char type[12]="";
5155 
5156       if(conn->bits.type_set)
5157         snprintf(type, sizeof(type), ";type=%c",
5158                  data->set.prefer_ascii?'A':
5159                  (data->set.ftp_list_only?'D':'I'));
5160 
5161       /*
5162        * This synthesized URL isn't always right--suffixes like ;type=A are
5163        * stripped off. It would be better to work directly from the original
5164        * URL and simply replace the port part of it.
5165        */
5166       url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
5167                     conn->bits.ipv6_ip?"[":"", conn->host.name,
5168                     conn->bits.ipv6_ip?"]":"", conn->remote_port,
5169                     data->state.slash_removed?"/":"", data->state.path,
5170                     type);
5171       if(!url)
5172         return CURLE_OUT_OF_MEMORY;
5173 
5174       if(data->change.url_alloc) {
5175         Curl_safefree(data->change.url);
5176         data->change.url_alloc = FALSE;
5177       }
5178 
5179       data->change.url = url;
5180       data->change.url_alloc = TRUE;
5181     }
5182   }
5183   else if(portptr) {
5184     /* no CURLOPT_PORT given, extract the one from the URL */
5185 
5186     char *rest;
5187     long port;
5188 
5189     port=strtol(portptr+1, &rest, 10);  /* Port number must be decimal */
5190 
5191     if((port < 0) || (port > 0xffff)) {
5192       /* Single unix standard says port numbers are 16 bits long */
5193       failf(data, "Port number out of range");
5194       return CURLE_URL_MALFORMAT;
5195     }
5196 
5197     else if(rest != &portptr[1]) {
5198       *portptr = '\0'; /* cut off the name there */
5199       conn->remote_port = curlx_ultous(port);
5200     }
5201     else
5202       /* Browser behavior adaptation. If there's a colon with no digits after,
5203          just cut off the name there which makes us ignore the colon and just
5204          use the default port. Firefox and Chrome both do that. */
5205       *portptr = '\0';
5206   }
5207 
5208   /* only if remote_port was not already parsed off the URL we use the
5209      default port number */
5210   if(conn->remote_port < 0)
5211     conn->remote_port = (unsigned short)conn->given->defport;
5212 
5213   return CURLE_OK;
5214 }
5215 
5216 /*
5217  * Override the login details from the URL with that in the CURLOPT_USERPWD
5218  * option or a .netrc file, if applicable.
5219  */
override_login(struct SessionHandle * data,struct connectdata * conn,char ** userp,char ** passwdp,char ** optionsp)5220 static CURLcode override_login(struct SessionHandle *data,
5221                                struct connectdata *conn,
5222                                char **userp, char **passwdp, char **optionsp)
5223 {
5224   if(data->set.str[STRING_USERNAME]) {
5225     free(*userp);
5226     *userp = strdup(data->set.str[STRING_USERNAME]);
5227     if(!*userp)
5228       return CURLE_OUT_OF_MEMORY;
5229   }
5230 
5231   if(data->set.str[STRING_PASSWORD]) {
5232     free(*passwdp);
5233     *passwdp = strdup(data->set.str[STRING_PASSWORD]);
5234     if(!*passwdp)
5235       return CURLE_OUT_OF_MEMORY;
5236   }
5237 
5238   if(data->set.str[STRING_OPTIONS]) {
5239     free(*optionsp);
5240     *optionsp = strdup(data->set.str[STRING_OPTIONS]);
5241     if(!*optionsp)
5242       return CURLE_OUT_OF_MEMORY;
5243   }
5244 
5245   conn->bits.netrc = FALSE;
5246   if(data->set.use_netrc != CURL_NETRC_IGNORED) {
5247     int ret = Curl_parsenetrc(conn->host.name,
5248                               userp, passwdp,
5249                               data->set.str[STRING_NETRC_FILE]);
5250     if(ret > 0) {
5251       infof(data, "Couldn't find host %s in the "
5252             DOT_CHAR "netrc file; using defaults\n",
5253             conn->host.name);
5254     }
5255     else if(ret < 0) {
5256       return CURLE_OUT_OF_MEMORY;
5257     }
5258     else {
5259       /* set bits.netrc TRUE to remember that we got the name from a .netrc
5260          file, so that it is safe to use even if we followed a Location: to a
5261          different host or similar. */
5262       conn->bits.netrc = TRUE;
5263 
5264       conn->bits.user_passwd = TRUE; /* enable user+password */
5265     }
5266   }
5267 
5268   return CURLE_OK;
5269 }
5270 
5271 /*
5272  * Set the login details so they're available in the connection
5273  */
set_login(struct connectdata * conn,const char * user,const char * passwd,const char * options)5274 static CURLcode set_login(struct connectdata *conn,
5275                           const char *user, const char *passwd,
5276                           const char *options)
5277 {
5278   CURLcode result = CURLE_OK;
5279 
5280   /* If our protocol needs a password and we have none, use the defaults */
5281   if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
5282     /* Store the default user */
5283     conn->user = strdup(CURL_DEFAULT_USER);
5284 
5285     /* Store the default password */
5286     if(conn->user)
5287       conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
5288     else
5289       conn->passwd = NULL;
5290 
5291     /* This is the default password, so DON'T set conn->bits.user_passwd */
5292   }
5293   else {
5294     /* Store the user, zero-length if not set */
5295     conn->user = strdup(user);
5296 
5297     /* Store the password (only if user is present), zero-length if not set */
5298     if(conn->user)
5299       conn->passwd = strdup(passwd);
5300     else
5301       conn->passwd = NULL;
5302   }
5303 
5304   if(!conn->user || !conn->passwd)
5305     result = CURLE_OUT_OF_MEMORY;
5306 
5307   /* Store the options, null if not set */
5308   if(!result && options[0]) {
5309     conn->options = strdup(options);
5310 
5311     if(!conn->options)
5312       result = CURLE_OUT_OF_MEMORY;
5313   }
5314 
5315   return result;
5316 }
5317 
5318 /*
5319  * Parses a "host:port" string to connect to.
5320  * The hostname and the port may be empty; in this case, NULL is returned for
5321  * the hostname and -1 for the port.
5322  */
parse_connect_to_host_port(struct SessionHandle * data,const char * host,char ** hostname_result,int * port_result)5323 static CURLcode parse_connect_to_host_port(struct SessionHandle *data,
5324                                            const char *host,
5325                                            char **hostname_result,
5326                                            int *port_result)
5327 {
5328   char *host_dup;
5329   char *hostptr;
5330   char *host_portno;
5331   char *portptr;
5332   int port = -1;
5333 
5334   *hostname_result = NULL;
5335   *port_result = -1;
5336 
5337   if(!host || !*host)
5338     return CURLE_OK;
5339 
5340   host_dup = strdup(host);
5341   if(!host_dup)
5342     return CURLE_OUT_OF_MEMORY;
5343 
5344   hostptr = host_dup;
5345 
5346   /* start scanning for port number at this point */
5347   portptr = hostptr;
5348 
5349   /* detect and extract RFC6874-style IPv6-addresses */
5350   if(*hostptr == '[') {
5351     char *ptr = ++hostptr; /* advance beyond the initial bracket */
5352     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
5353       ptr++;
5354     if(*ptr == '%') {
5355       /* There might be a zone identifier */
5356       if(strncmp("%25", ptr, 3))
5357         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
5358       ptr++;
5359       /* Allow unreserved characters as defined in RFC 3986 */
5360       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
5361                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
5362         ptr++;
5363     }
5364     if(*ptr == ']')
5365       /* yeps, it ended nicely with a bracket as well */
5366       *ptr++ = '\0';
5367     else
5368       infof(data, "Invalid IPv6 address format\n");
5369     portptr = ptr;
5370     /* Note that if this didn't end with a bracket, we still advanced the
5371      * hostptr first, but I can't see anything wrong with that as no host
5372      * name nor a numeric can legally start with a bracket.
5373      */
5374   }
5375 
5376   /* Get port number off server.com:1080 */
5377   host_portno = strchr(portptr, ':');
5378   if(host_portno) {
5379     char *endp = NULL;
5380     *host_portno = '\0'; /* cut off number from host name */
5381     host_portno++;
5382     if(*host_portno) {
5383       long portparse = strtol(host_portno, &endp, 10);
5384       if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
5385         infof(data, "No valid port number in connect to host string (%s)\n",
5386               host_portno);
5387         hostptr = NULL;
5388         port = -1;
5389       }
5390       else
5391         port = (int)portparse; /* we know it will fit */
5392     }
5393   }
5394 
5395   /* now, clone the cleaned host name */
5396   if(hostptr) {
5397     *hostname_result = strdup(hostptr);
5398     if(!*hostname_result) {
5399       free(host_dup);
5400       return CURLE_OUT_OF_MEMORY;
5401     }
5402   }
5403 
5404   *port_result = port;
5405 
5406   free(host_dup);
5407   return CURLE_OK;
5408 }
5409 
5410 /*
5411  * Parses one "connect to" string in the form:
5412  * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
5413  */
parse_connect_to_string(struct SessionHandle * data,struct connectdata * conn,const char * conn_to_host,char ** host_result,int * port_result)5414 static CURLcode parse_connect_to_string(struct SessionHandle *data,
5415                                         struct connectdata *conn,
5416                                         const char *conn_to_host,
5417                                         char **host_result,
5418                                         int *port_result)
5419 {
5420   CURLcode result = CURLE_OK;
5421   const char *ptr = conn_to_host;
5422   int host_match = FALSE;
5423   int port_match = FALSE;
5424 
5425   if(*ptr == ':') {
5426     /* an empty hostname always matches */
5427     host_match = TRUE;
5428     ptr++;
5429   }
5430   else {
5431     /* check whether the URL's hostname matches */
5432     size_t hostname_to_match_len;
5433     char *hostname_to_match = aprintf("%s%s%s",
5434                                       conn->bits.ipv6_ip ? "[" : "",
5435                                       conn->host.name,
5436                                       conn->bits.ipv6_ip ? "]" : "");
5437     if(!hostname_to_match)
5438       return CURLE_OUT_OF_MEMORY;
5439     hostname_to_match_len = strlen(hostname_to_match);
5440     host_match = curl_strnequal(ptr, hostname_to_match, hostname_to_match_len);
5441     free(hostname_to_match);
5442     ptr += hostname_to_match_len;
5443 
5444     host_match = host_match && *ptr == ':';
5445     ptr++;
5446   }
5447 
5448   if(host_match) {
5449     if(*ptr == ':') {
5450       /* an empty port always matches */
5451       port_match = TRUE;
5452       ptr++;
5453     }
5454     else {
5455       /* check whether the URL's port matches */
5456       char *ptr_next = strchr(ptr, ':');
5457       if(ptr_next) {
5458         char *endp = NULL;
5459         long port_to_match = strtol(ptr, &endp, 10);
5460         if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
5461           port_match = TRUE;
5462           ptr = ptr_next + 1;
5463         }
5464       }
5465     }
5466   }
5467 
5468   if(host_match && port_match) {
5469     /* parse the hostname and port to connect to */
5470     result = parse_connect_to_host_port(data, ptr, host_result, port_result);
5471   }
5472 
5473   return result;
5474 }
5475 
5476 /*
5477  * Processes all strings in the "connect to" slist, and uses the "connect
5478  * to host" and "connect to port" of the first string that matches.
5479  */
parse_connect_to_slist(struct SessionHandle * data,struct connectdata * conn,struct curl_slist * conn_to_host)5480 static CURLcode parse_connect_to_slist(struct SessionHandle *data,
5481                                        struct connectdata *conn,
5482                                        struct curl_slist *conn_to_host)
5483 {
5484   CURLcode result = CURLE_OK;
5485   char *host = NULL;
5486   int port = 0;
5487 
5488   while(conn_to_host && !host) {
5489     result = parse_connect_to_string(data, conn, conn_to_host->data,
5490                                      &host, &port);
5491     if(result)
5492       return result;
5493 
5494     if(host && *host) {
5495       bool ipv6host;
5496       conn->conn_to_host.rawalloc = host;
5497       conn->conn_to_host.name = host;
5498       conn->bits.conn_to_host = TRUE;
5499 
5500       ipv6host = strchr(host, ':') != NULL;
5501       infof(data, "Connecting to hostname: %s%s%s\n",
5502             ipv6host ? "[" : "", host, ipv6host ? "]" : "");
5503     }
5504     else {
5505       /* no "connect to host" */
5506       conn->bits.conn_to_host = FALSE;
5507       free(host);
5508     }
5509 
5510     if(port >= 0) {
5511       conn->conn_to_port = port;
5512       conn->bits.conn_to_port = TRUE;
5513       infof(data, "Connecting to port: %d\n", port);
5514     }
5515     else {
5516       /* no "connect to port" */
5517       conn->bits.conn_to_port = FALSE;
5518     }
5519 
5520     conn_to_host = conn_to_host->next;
5521   }
5522 
5523   return result;
5524 }
5525 
5526 /*************************************************************
5527  * Resolve the address of the server or proxy
5528  *************************************************************/
resolve_server(struct SessionHandle * data,struct connectdata * conn,bool * async)5529 static CURLcode resolve_server(struct SessionHandle *data,
5530                                struct connectdata *conn,
5531                                bool *async)
5532 {
5533   CURLcode result=CURLE_OK;
5534   long timeout_ms = Curl_timeleft(data, NULL, TRUE);
5535 
5536   /*************************************************************
5537    * Resolve the name of the server or proxy
5538    *************************************************************/
5539   if(conn->bits.reuse)
5540     /* We're reusing the connection - no need to resolve anything, and
5541        fix_hostname() was called already in create_conn() for the re-use
5542        case. */
5543     *async = FALSE;
5544 
5545   else {
5546     /* this is a fresh connect */
5547     int rc;
5548     struct Curl_dns_entry *hostaddr;
5549 
5550 #ifdef USE_UNIX_SOCKETS
5551     if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
5552       /* Unix domain sockets are local. The host gets ignored, just use the
5553        * specified domain socket address. Do not cache "DNS entries". There is
5554        * no DNS involved and we already have the filesystem path available */
5555       const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
5556 
5557       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
5558       if(!hostaddr)
5559         result = CURLE_OUT_OF_MEMORY;
5560       else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
5561         hostaddr->inuse++;
5562       else {
5563         /* Long paths are not supported for now */
5564         if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
5565           failf(data, "Unix socket path too long: '%s'", path);
5566           result = CURLE_COULDNT_RESOLVE_HOST;
5567         }
5568         else
5569           result = CURLE_OUT_OF_MEMORY;
5570         free(hostaddr);
5571         hostaddr = NULL;
5572       }
5573     }
5574     else
5575 #endif
5576     if(!conn->proxy.name || !*conn->proxy.name) {
5577       struct hostname *connhost;
5578       if(conn->bits.conn_to_host)
5579         connhost = &conn->conn_to_host;
5580       else
5581         connhost = &conn->host;
5582 
5583       /* If not connecting via a proxy, extract the port from the URL, if it is
5584        * there, thus overriding any defaults that might have been set above. */
5585       if(conn->bits.conn_to_port)
5586         conn->port = conn->conn_to_port;
5587       else
5588         conn->port = conn->remote_port; /* it is the same port */
5589 
5590       /* Resolve target host right on */
5591       rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
5592                                &hostaddr, timeout_ms);
5593       if(rc == CURLRESOLV_PENDING)
5594         *async = TRUE;
5595 
5596       else if(rc == CURLRESOLV_TIMEDOUT)
5597         result = CURLE_OPERATION_TIMEDOUT;
5598 
5599       else if(!hostaddr) {
5600         failf(data, "Couldn't resolve host '%s'", connhost->dispname);
5601         result =  CURLE_COULDNT_RESOLVE_HOST;
5602         /* don't return yet, we need to clean up the timeout first */
5603       }
5604     }
5605     else {
5606       /* This is a proxy that hasn't been resolved yet. */
5607 
5608       /* resolve proxy */
5609       rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
5610                                &hostaddr, timeout_ms);
5611 
5612       if(rc == CURLRESOLV_PENDING)
5613         *async = TRUE;
5614 
5615       else if(rc == CURLRESOLV_TIMEDOUT)
5616         result = CURLE_OPERATION_TIMEDOUT;
5617 
5618       else if(!hostaddr) {
5619         failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
5620         result = CURLE_COULDNT_RESOLVE_PROXY;
5621         /* don't return yet, we need to clean up the timeout first */
5622       }
5623     }
5624     DEBUGASSERT(conn->dns_entry == NULL);
5625     conn->dns_entry = hostaddr;
5626   }
5627 
5628   return result;
5629 }
5630 
5631 /*
5632  * Cleanup the connection just allocated before we can move along and use the
5633  * previously existing one.  All relevant data is copied over and old_conn is
5634  * ready for freeing once this function returns.
5635  */
reuse_conn(struct connectdata * old_conn,struct connectdata * conn)5636 static void reuse_conn(struct connectdata *old_conn,
5637                        struct connectdata *conn)
5638 {
5639   free_fixed_hostname(&old_conn->proxy);
5640   free(old_conn->proxy.rawalloc);
5641 
5642   /* free the SSL config struct from this connection struct as this was
5643      allocated in vain and is targeted for destruction */
5644   Curl_free_ssl_config(&old_conn->ssl_config);
5645 
5646   conn->data = old_conn->data;
5647 
5648   /* get the user+password information from the old_conn struct since it may
5649    * be new for this request even when we re-use an existing connection */
5650   conn->bits.user_passwd = old_conn->bits.user_passwd;
5651   if(conn->bits.user_passwd) {
5652     /* use the new user name and password though */
5653     Curl_safefree(conn->user);
5654     Curl_safefree(conn->passwd);
5655     conn->user = old_conn->user;
5656     conn->passwd = old_conn->passwd;
5657     old_conn->user = NULL;
5658     old_conn->passwd = NULL;
5659   }
5660 
5661   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
5662   if(conn->bits.proxy_user_passwd) {
5663     /* use the new proxy user name and proxy password though */
5664     Curl_safefree(conn->proxyuser);
5665     Curl_safefree(conn->proxypasswd);
5666     conn->proxyuser = old_conn->proxyuser;
5667     conn->proxypasswd = old_conn->proxypasswd;
5668     old_conn->proxyuser = NULL;
5669     old_conn->proxypasswd = NULL;
5670   }
5671 
5672   /* host can change, when doing keepalive with a proxy or if the case is
5673      different this time etc */
5674   free_fixed_hostname(&conn->host);
5675   free_fixed_hostname(&conn->conn_to_host);
5676   Curl_safefree(conn->host.rawalloc);
5677   Curl_safefree(conn->conn_to_host.rawalloc);
5678   conn->host=old_conn->host;
5679   conn->bits.conn_to_host = old_conn->bits.conn_to_host;
5680   conn->conn_to_host = old_conn->conn_to_host;
5681   conn->bits.conn_to_port = old_conn->bits.conn_to_port;
5682   conn->conn_to_port = old_conn->conn_to_port;
5683 
5684   /* persist connection info in session handle */
5685   Curl_persistconninfo(conn);
5686 
5687   conn_reset_all_postponed_data(old_conn); /* free buffers */
5688   conn_reset_all_postponed_data(conn);     /* reset unprocessed data */
5689 
5690   /* re-use init */
5691   conn->bits.reuse = TRUE; /* yes, we're re-using here */
5692 
5693   Curl_safefree(old_conn->user);
5694   Curl_safefree(old_conn->passwd);
5695   Curl_safefree(old_conn->proxyuser);
5696   Curl_safefree(old_conn->proxypasswd);
5697   Curl_safefree(old_conn->localdev);
5698 
5699   Curl_llist_destroy(old_conn->send_pipe, NULL);
5700   Curl_llist_destroy(old_conn->recv_pipe, NULL);
5701 
5702   old_conn->send_pipe = NULL;
5703   old_conn->recv_pipe = NULL;
5704 
5705   Curl_safefree(old_conn->master_buffer);
5706 }
5707 
5708 /**
5709  * create_conn() sets up a new connectdata struct, or re-uses an already
5710  * existing one, and resolves host name.
5711  *
5712  * if this function returns CURLE_OK and *async is set to TRUE, the resolve
5713  * response will be coming asynchronously. If *async is FALSE, the name is
5714  * already resolved.
5715  *
5716  * @param data The sessionhandle pointer
5717  * @param in_connect is set to the next connection data pointer
5718  * @param async is set TRUE when an async DNS resolution is pending
5719  * @see Curl_setup_conn()
5720  *
5721  * *NOTE* this function assigns the conn->data pointer!
5722  */
5723 
create_conn(struct SessionHandle * data,struct connectdata ** in_connect,bool * async)5724 static CURLcode create_conn(struct SessionHandle *data,
5725                             struct connectdata **in_connect,
5726                             bool *async)
5727 {
5728   CURLcode result = CURLE_OK;
5729   struct connectdata *conn;
5730   struct connectdata *conn_temp = NULL;
5731   size_t urllen;
5732   char *user = NULL;
5733   char *passwd = NULL;
5734   char *options = NULL;
5735   bool reuse;
5736   char *proxy = NULL;
5737   bool prot_missing = FALSE;
5738   bool connections_available = TRUE;
5739   bool force_reuse = FALSE;
5740   bool waitpipe = FALSE;
5741   size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
5742   size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
5743 
5744   *async = FALSE;
5745 
5746   /*************************************************************
5747    * Check input data
5748    *************************************************************/
5749 
5750   if(!data->change.url) {
5751     result = CURLE_URL_MALFORMAT;
5752     goto out;
5753   }
5754 
5755   /* First, split up the current URL in parts so that we can use the
5756      parts for checking against the already present connections. In order
5757      to not have to modify everything at once, we allocate a temporary
5758      connection data struct and fill in for comparison purposes. */
5759   conn = allocate_conn(data);
5760 
5761   if(!conn) {
5762     result = CURLE_OUT_OF_MEMORY;
5763     goto out;
5764   }
5765 
5766   /* We must set the return variable as soon as possible, so that our
5767      parent can cleanup any possible allocs we may have done before
5768      any failure */
5769   *in_connect = conn;
5770 
5771   /* This initing continues below, see the comment "Continue connectdata
5772    * initialization here" */
5773 
5774   /***********************************************************
5775    * We need to allocate memory to store the path in. We get the size of the
5776    * full URL to be sure, and we need to make it at least 256 bytes since
5777    * other parts of the code will rely on this fact
5778    ***********************************************************/
5779 #define LEAST_PATH_ALLOC 256
5780   urllen=strlen(data->change.url);
5781   if(urllen < LEAST_PATH_ALLOC)
5782     urllen=LEAST_PATH_ALLOC;
5783 
5784   /*
5785    * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
5786    * 1 - an extra terminating zero
5787    * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
5788    */
5789 
5790   Curl_safefree(data->state.pathbuffer);
5791   data->state.path = NULL;
5792 
5793   data->state.pathbuffer = malloc(urllen+2);
5794   if(NULL == data->state.pathbuffer) {
5795     result = CURLE_OUT_OF_MEMORY; /* really bad error */
5796     goto out;
5797   }
5798   data->state.path = data->state.pathbuffer;
5799 
5800   conn->host.rawalloc = malloc(urllen+2);
5801   if(NULL == conn->host.rawalloc) {
5802     Curl_safefree(data->state.pathbuffer);
5803     data->state.path = NULL;
5804     result = CURLE_OUT_OF_MEMORY;
5805     goto out;
5806   }
5807 
5808   conn->host.name = conn->host.rawalloc;
5809   conn->host.name[0] = 0;
5810 
5811   user = strdup("");
5812   passwd = strdup("");
5813   options = strdup("");
5814   if(!user || !passwd || !options) {
5815     result = CURLE_OUT_OF_MEMORY;
5816     goto out;
5817   }
5818 
5819   result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
5820                                &options);
5821   if(result)
5822     goto out;
5823 
5824   /*************************************************************
5825    * No protocol part in URL was used, add it!
5826    *************************************************************/
5827   if(prot_missing) {
5828     /* We're guessing prefixes here and if we're told to use a proxy or if
5829        we're gonna follow a Location: later or... then we need the protocol
5830        part added so that we have a valid URL. */
5831     char *reurl;
5832     char *ch_lower;
5833 
5834     reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
5835 
5836     if(!reurl) {
5837       result = CURLE_OUT_OF_MEMORY;
5838       goto out;
5839     }
5840 
5841     /* Change protocol prefix to lower-case */
5842     for(ch_lower = reurl; *ch_lower != ':'; ch_lower++)
5843       *ch_lower = (char)TOLOWER(*ch_lower);
5844 
5845     if(data->change.url_alloc) {
5846       Curl_safefree(data->change.url);
5847       data->change.url_alloc = FALSE;
5848     }
5849 
5850     data->change.url = reurl;
5851     data->change.url_alloc = TRUE; /* free this later */
5852   }
5853 
5854   /*************************************************************
5855    * If the protocol can't handle url query strings, then cut
5856    * off the unhandable part
5857    *************************************************************/
5858   if((conn->given->flags&PROTOPT_NOURLQUERY)) {
5859     char *path_q_sep = strchr(conn->data->state.path, '?');
5860     if(path_q_sep) {
5861       /* according to rfc3986, allow the query (?foo=bar)
5862          also on protocols that can't handle it.
5863 
5864          cut the string-part after '?'
5865       */
5866 
5867       /* terminate the string */
5868       path_q_sep[0] = 0;
5869     }
5870   }
5871 
5872   if(data->set.str[STRING_BEARER]) {
5873     conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
5874     if(!conn->oauth_bearer) {
5875       result = CURLE_OUT_OF_MEMORY;
5876       goto out;
5877     }
5878   }
5879 
5880 #ifndef CURL_DISABLE_PROXY
5881   /*************************************************************
5882    * Extract the user and password from the authentication string
5883    *************************************************************/
5884   if(conn->bits.proxy_user_passwd) {
5885     result = parse_proxy_auth(data, conn);
5886     if(result)
5887       goto out;
5888   }
5889 
5890   /*************************************************************
5891    * Detect what (if any) proxy to use
5892    *************************************************************/
5893   if(data->set.str[STRING_PROXY]) {
5894     proxy = strdup(data->set.str[STRING_PROXY]);
5895     /* if global proxy is set, this is it */
5896     if(NULL == proxy) {
5897       failf(data, "memory shortage");
5898       result = CURLE_OUT_OF_MEMORY;
5899       goto out;
5900     }
5901   }
5902 
5903   if(data->set.str[STRING_NOPROXY] &&
5904      check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
5905     free(proxy);  /* proxy is in exception list */
5906     proxy = NULL;
5907   }
5908   else if(!proxy)
5909     proxy = detect_proxy(conn);
5910 
5911 #ifdef USE_UNIX_SOCKETS
5912   if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
5913     free(proxy);  /* Unix domain sockets cannot be proxied, so disable it */
5914     proxy = NULL;
5915   }
5916 #endif
5917 
5918   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
5919     free(proxy);  /* Don't bother with an empty proxy string or if the
5920                      protocol doesn't work with network */
5921     proxy = NULL;
5922   }
5923 
5924   /***********************************************************************
5925    * If this is supposed to use a proxy, we need to figure out the proxy host
5926    * name, proxy type and port number, so that we can re-use an existing
5927    * connection that may exist registered to the same proxy host.
5928    ***********************************************************************/
5929   if(proxy) {
5930     result = parse_proxy(data, conn, proxy);
5931 
5932     free(proxy); /* parse_proxy copies the proxy string */
5933     proxy = NULL;
5934 
5935     if(result)
5936       goto out;
5937 
5938     if((conn->proxytype == CURLPROXY_HTTP) ||
5939        (conn->proxytype == CURLPROXY_HTTP_1_0)) {
5940 #ifdef CURL_DISABLE_HTTP
5941       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
5942       result = CURLE_UNSUPPORTED_PROTOCOL;
5943       goto out;
5944 #else
5945       /* force this connection's protocol to become HTTP if not already
5946          compatible - if it isn't tunneling through */
5947       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
5948          !conn->bits.tunnel_proxy)
5949         conn->handler = &Curl_handler_http;
5950 
5951       conn->bits.httpproxy = TRUE;
5952 #endif
5953     }
5954     else {
5955       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
5956       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
5957     }
5958     conn->bits.proxy = TRUE;
5959   }
5960   else {
5961     /* we aren't using the proxy after all... */
5962     conn->bits.proxy = FALSE;
5963     conn->bits.httpproxy = FALSE;
5964     conn->bits.proxy_user_passwd = FALSE;
5965     conn->bits.tunnel_proxy = FALSE;
5966   }
5967 
5968 #endif /* CURL_DISABLE_PROXY */
5969 
5970   /*************************************************************
5971    * If the protocol is using SSL and HTTP proxy is used, we set
5972    * the tunnel_proxy bit.
5973    *************************************************************/
5974   if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
5975     conn->bits.tunnel_proxy = TRUE;
5976 
5977   /*************************************************************
5978    * Figure out the remote port number and fix it in the URL
5979    *************************************************************/
5980   result = parse_remote_port(data, conn);
5981   if(result)
5982     goto out;
5983 
5984   /* Check for overridden login details and set them accordingly so they
5985      they are known when protocol->setup_connection is called! */
5986   result = override_login(data, conn, &user, &passwd, &options);
5987   if(result)
5988     goto out;
5989   result = set_login(conn, user, passwd, options);
5990   if(result)
5991     goto out;
5992 
5993   /*************************************************************
5994    * Process the "connect to" linked list of hostname/port mappings.
5995    * Do this after the remote port number has been fixed in the URL.
5996    *************************************************************/
5997   result = parse_connect_to_slist(data, conn, data->set.connect_to);
5998   if(result)
5999     goto out;
6000 
6001   /*************************************************************
6002    * IDN-fix the hostnames
6003    *************************************************************/
6004   fix_hostname(data, conn, &conn->host);
6005   if(conn->bits.conn_to_host)
6006     fix_hostname(data, conn, &conn->conn_to_host);
6007   if(conn->proxy.name && *conn->proxy.name)
6008     fix_hostname(data, conn, &conn->proxy);
6009 
6010   /*************************************************************
6011    * Check whether the host and the "connect to host" are equal.
6012    * Do this after the hostnames have been IDN-fixed .
6013    *************************************************************/
6014   if(conn->bits.conn_to_host &&
6015       Curl_raw_equal(conn->conn_to_host.name, conn->host.name)) {
6016     conn->bits.conn_to_host = FALSE;
6017   }
6018 
6019   /*************************************************************
6020    * Check whether the port and the "connect to port" are equal.
6021    * Do this after the remote port number has been fixed in the URL.
6022    *************************************************************/
6023   if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
6024     conn->bits.conn_to_port = FALSE;
6025   }
6026 
6027   /*************************************************************
6028    * If the "connect to" feature is used with an HTTP proxy,
6029    * we set the tunnel_proxy bit.
6030    *************************************************************/
6031   if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
6032       conn->bits.httpproxy)
6033     conn->bits.tunnel_proxy = TRUE;
6034 
6035   /*************************************************************
6036    * Setup internals depending on protocol. Needs to be done after
6037    * we figured out what/if proxy to use.
6038    *************************************************************/
6039   result = setup_connection_internals(conn);
6040   if(result)
6041     goto out;
6042 
6043   conn->recv[FIRSTSOCKET] = Curl_recv_plain;
6044   conn->send[FIRSTSOCKET] = Curl_send_plain;
6045   conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
6046   conn->send[SECONDARYSOCKET] = Curl_send_plain;
6047 
6048   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
6049 
6050   /***********************************************************************
6051    * file: is a special case in that it doesn't need a network connection
6052    ***********************************************************************/
6053 #ifndef CURL_DISABLE_FILE
6054   if(conn->handler->flags & PROTOPT_NONETWORK) {
6055     bool done;
6056     /* this is supposed to be the connect function so we better at least check
6057        that the file is present here! */
6058     DEBUGASSERT(conn->handler->connect_it);
6059     result = conn->handler->connect_it(conn, &done);
6060 
6061     /* Setup a "faked" transfer that'll do nothing */
6062     if(!result) {
6063       conn->data = data;
6064       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
6065 
6066       Curl_conncache_add_conn(data->state.conn_cache, conn);
6067 
6068       /*
6069        * Setup whatever necessary for a resumed transfer
6070        */
6071       result = setup_range(data);
6072       if(result) {
6073         DEBUGASSERT(conn->handler->done);
6074         /* we ignore the return code for the protocol-specific DONE */
6075         (void)conn->handler->done(conn, result, FALSE);
6076         goto out;
6077       }
6078 
6079       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
6080                           -1, NULL); /* no upload */
6081     }
6082 
6083     /* since we skip do_init() */
6084     Curl_init_do(data, conn);
6085 
6086     goto out;
6087   }
6088 #endif
6089 
6090   /* Get a cloned copy of the SSL config situation stored in the
6091      connection struct. But to get this going nicely, we must first make
6092      sure that the strings in the master copy are pointing to the correct
6093      strings in the session handle strings array!
6094 
6095      Keep in mind that the pointers in the master copy are pointing to strings
6096      that will be freed as part of the SessionHandle struct, but all cloned
6097      copies will be separately allocated.
6098   */
6099   data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
6100   data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
6101   data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
6102   data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
6103   data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
6104   data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
6105   data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
6106 #ifdef USE_TLS_SRP
6107   data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
6108   data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
6109 #endif
6110 
6111   if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
6112     result = CURLE_OUT_OF_MEMORY;
6113     goto out;
6114   }
6115 
6116   prune_dead_connections(data);
6117 
6118   /*************************************************************
6119    * Check the current list of connections to see if we can
6120    * re-use an already existing one or if we have to create a
6121    * new one.
6122    *************************************************************/
6123 
6124   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
6125      we only acknowledge this option if this is not a re-used connection
6126      already (which happens due to follow-location or during a HTTP
6127      authentication phase). */
6128   if(data->set.reuse_fresh && !data->state.this_is_a_follow)
6129     reuse = FALSE;
6130   else
6131     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
6132 
6133   /* If we found a reusable connection, we may still want to
6134      open a new connection if we are pipelining. */
6135   if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
6136     size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
6137     if(pipelen > 0) {
6138       infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
6139             conn_temp->connection_id, pipelen);
6140 
6141       if(conn_temp->bundle->num_connections < max_host_connections &&
6142          data->state.conn_cache->num_connections < max_total_connections) {
6143         /* We want a new connection anyway */
6144         reuse = FALSE;
6145 
6146         infof(data, "We can reuse, but we want a new connection anyway\n");
6147       }
6148     }
6149   }
6150 
6151   if(reuse) {
6152     /*
6153      * We already have a connection for this, we got the former connection
6154      * in the conn_temp variable and thus we need to cleanup the one we
6155      * just allocated before we can move along and use the previously
6156      * existing one.
6157      */
6158     conn_temp->inuse = TRUE; /* mark this as being in use so that no other
6159                                 handle in a multi stack may nick it */
6160     reuse_conn(conn, conn_temp);
6161     free(conn);          /* we don't need this anymore */
6162     conn = conn_temp;
6163     *in_connect = conn;
6164 
6165     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
6166           conn->connection_id,
6167           conn->bits.proxy?"proxy":"host",
6168           conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
6169   }
6170   else {
6171     /* We have decided that we want a new connection. However, we may not
6172        be able to do that if we have reached the limit of how many
6173        connections we are allowed to open. */
6174     struct connectbundle *bundle = NULL;
6175 
6176     if(conn->handler->flags & PROTOPT_ALPN_NPN) {
6177       /* The protocol wants it, so set the bits if enabled in the easy handle
6178          (default) */
6179       if(data->set.ssl_enable_alpn)
6180         conn->bits.tls_enable_alpn = TRUE;
6181       if(data->set.ssl_enable_npn)
6182         conn->bits.tls_enable_npn = TRUE;
6183     }
6184 
6185     if(waitpipe)
6186       /* There is a connection that *might* become usable for pipelining
6187          "soon", and we wait for that */
6188       connections_available = FALSE;
6189     else
6190       bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
6191 
6192     if(max_host_connections > 0 && bundle &&
6193        (bundle->num_connections >= max_host_connections)) {
6194       struct connectdata *conn_candidate;
6195 
6196       /* The bundle is full. Let's see if we can kill a connection. */
6197       conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
6198 
6199       if(conn_candidate) {
6200         /* Set the connection's owner correctly, then kill it */
6201         conn_candidate->data = data;
6202         (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
6203       }
6204       else {
6205         infof(data, "No more connections allowed to host: %d\n",
6206               max_host_connections);
6207         connections_available = FALSE;
6208       }
6209     }
6210 
6211     if(connections_available &&
6212        (max_total_connections > 0) &&
6213        (data->state.conn_cache->num_connections >= max_total_connections)) {
6214       struct connectdata *conn_candidate;
6215 
6216       /* The cache is full. Let's see if we can kill a connection. */
6217       conn_candidate = Curl_oldest_idle_connection(data);
6218 
6219       if(conn_candidate) {
6220         /* Set the connection's owner correctly, then kill it */
6221         conn_candidate->data = data;
6222         (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
6223       }
6224       else {
6225         infof(data, "No connections available in cache\n");
6226         connections_available = FALSE;
6227       }
6228     }
6229 
6230     if(!connections_available) {
6231       infof(data, "No connections available.\n");
6232 
6233       conn_free(conn);
6234       *in_connect = NULL;
6235 
6236       result = CURLE_NO_CONNECTION_AVAILABLE;
6237       goto out;
6238     }
6239     else {
6240       /*
6241        * This is a brand new connection, so let's store it in the connection
6242        * cache of ours!
6243        */
6244       Curl_conncache_add_conn(data->state.conn_cache, conn);
6245     }
6246 
6247 #if defined(USE_NTLM)
6248     /* If NTLM is requested in a part of this connection, make sure we don't
6249        assume the state is fine as this is a fresh connection and NTLM is
6250        connection based. */
6251     if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
6252        data->state.authhost.done) {
6253       infof(data, "NTLM picked AND auth done set, clear picked!\n");
6254       data->state.authhost.picked = CURLAUTH_NONE;
6255       data->state.authhost.done = FALSE;
6256     }
6257 
6258     if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
6259        data->state.authproxy.done) {
6260       infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
6261       data->state.authproxy.picked = CURLAUTH_NONE;
6262       data->state.authproxy.done = FALSE;
6263     }
6264 #endif
6265   }
6266 
6267   /* Mark the connection as used */
6268   conn->inuse = TRUE;
6269 
6270   /* Setup and init stuff before DO starts, in preparing for the transfer. */
6271   Curl_init_do(data, conn);
6272 
6273   /*
6274    * Setup whatever necessary for a resumed transfer
6275    */
6276   result = setup_range(data);
6277   if(result)
6278     goto out;
6279 
6280   /* Continue connectdata initialization here. */
6281 
6282   /*
6283    * Inherit the proper values from the urldata struct AFTER we have arranged
6284    * the persistent connection stuff
6285    */
6286   conn->seek_func = data->set.seek_func;
6287   conn->seek_client = data->set.seek_client;
6288 
6289   /*************************************************************
6290    * Resolve the address of the server or proxy
6291    *************************************************************/
6292   result = resolve_server(data, conn, async);
6293 
6294   out:
6295 
6296   free(options);
6297   free(passwd);
6298   free(user);
6299   free(proxy);
6300   return result;
6301 }
6302 
6303 /* Curl_setup_conn() is called after the name resolve initiated in
6304  * create_conn() is all done.
6305  *
6306  * Curl_setup_conn() also handles reused connections
6307  *
6308  * conn->data MUST already have been setup fine (in create_conn)
6309  */
6310 
Curl_setup_conn(struct connectdata * conn,bool * protocol_done)6311 CURLcode Curl_setup_conn(struct connectdata *conn,
6312                          bool *protocol_done)
6313 {
6314   CURLcode result = CURLE_OK;
6315   struct SessionHandle *data = conn->data;
6316 
6317   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
6318 
6319   if(conn->handler->flags & PROTOPT_NONETWORK) {
6320     /* nothing to setup when not using a network */
6321     *protocol_done = TRUE;
6322     return result;
6323   }
6324   *protocol_done = FALSE; /* default to not done */
6325 
6326   /* set proxy_connect_closed to false unconditionally already here since it
6327      is used strictly to provide extra information to a parent function in the
6328      case of proxy CONNECT failures and we must make sure we don't have it
6329      lingering set from a previous invoke */
6330   conn->bits.proxy_connect_closed = FALSE;
6331 
6332   /*
6333    * Set user-agent. Used for HTTP, but since we can attempt to tunnel
6334    * basically anything through a http proxy we can't limit this based on
6335    * protocol.
6336    */
6337   if(data->set.str[STRING_USERAGENT]) {
6338     Curl_safefree(conn->allocptr.uagent);
6339     conn->allocptr.uagent =
6340       aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
6341     if(!conn->allocptr.uagent)
6342       return CURLE_OUT_OF_MEMORY;
6343   }
6344 
6345   data->req.headerbytecount = 0;
6346 
6347 #ifdef CURL_DO_LINEEND_CONV
6348   data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
6349 #endif /* CURL_DO_LINEEND_CONV */
6350 
6351   /* set start time here for timeout purposes in the connect procedure, it
6352      is later set again for the progress meter purpose */
6353   conn->now = Curl_tvnow();
6354 
6355   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
6356     conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
6357     result = Curl_connecthost(conn, conn->dns_entry);
6358     if(result)
6359       return result;
6360   }
6361   else {
6362     Curl_pgrsTime(data, TIMER_CONNECT);    /* we're connected already */
6363     Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
6364     conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
6365     *protocol_done = TRUE;
6366     Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
6367     Curl_verboseconnect(conn);
6368   }
6369 
6370   conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
6371                                set this here perhaps a second time */
6372 
6373 #ifdef __EMX__
6374   /*
6375    * This check is quite a hack. We're calling _fsetmode to fix the problem
6376    * with fwrite converting newline characters (you get mangled text files,
6377    * and corrupted binary files when you download to stdout and redirect it to
6378    * a file).
6379    */
6380 
6381   if((data->set.out)->_handle == NULL) {
6382     _fsetmode(stdout, "b");
6383   }
6384 #endif
6385 
6386   return result;
6387 }
6388 
Curl_connect(struct SessionHandle * data,struct connectdata ** in_connect,bool * asyncp,bool * protocol_done)6389 CURLcode Curl_connect(struct SessionHandle *data,
6390                       struct connectdata **in_connect,
6391                       bool *asyncp,
6392                       bool *protocol_done)
6393 {
6394   CURLcode result;
6395 
6396   *asyncp = FALSE; /* assume synchronous resolves by default */
6397 
6398   /* call the stuff that needs to be called */
6399   result = create_conn(data, in_connect, asyncp);
6400 
6401   if(!result) {
6402     /* no error */
6403     if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
6404       /* pipelining */
6405       *protocol_done = TRUE;
6406     else if(!*asyncp) {
6407       /* DNS resolution is done: that's either because this is a reused
6408          connection, in which case DNS was unnecessary, or because DNS
6409          really did finish already (synch resolver/fast async resolve) */
6410       result = Curl_setup_conn(*in_connect, protocol_done);
6411     }
6412   }
6413 
6414   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
6415     *in_connect = NULL;
6416     return result;
6417   }
6418 
6419   if(result && *in_connect) {
6420     /* We're not allowed to return failure with memory left allocated
6421        in the connectdata struct, free those here */
6422     Curl_disconnect(*in_connect, FALSE); /* close the connection */
6423     *in_connect = NULL;           /* return a NULL */
6424   }
6425 
6426   return result;
6427 }
6428 
6429 /*
6430  * Curl_init_do() inits the readwrite session. This is inited each time (in
6431  * the DO function before the protocol-specific DO functions are invoked) for
6432  * a transfer, sometimes multiple times on the same SessionHandle. Make sure
6433  * nothing in here depends on stuff that are setup dynamically for the
6434  * transfer.
6435  *
6436  * Allow this function to get called with 'conn' set to NULL.
6437  */
6438 
Curl_init_do(struct SessionHandle * data,struct connectdata * conn)6439 CURLcode Curl_init_do(struct SessionHandle *data, struct connectdata *conn)
6440 {
6441   struct SingleRequest *k = &data->req;
6442 
6443   if(conn)
6444     conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
6445                                  * use */
6446 
6447   data->state.done = FALSE; /* *_done() is not called yet */
6448   data->state.expect100header = FALSE;
6449 
6450   if(data->set.opt_no_body)
6451     /* in HTTP lingo, no body means using the HEAD request... */
6452     data->set.httpreq = HTTPREQ_HEAD;
6453   else if(HTTPREQ_HEAD == data->set.httpreq)
6454     /* ... but if unset there really is no perfect method that is the
6455        "opposite" of HEAD but in reality most people probably think GET
6456        then. The important thing is that we can't let it remain HEAD if the
6457        opt_no_body is set FALSE since then we'll behave wrong when getting
6458        HTTP. */
6459     data->set.httpreq = HTTPREQ_GET;
6460 
6461   k->start = Curl_tvnow(); /* start time */
6462   k->now = k->start;   /* current time is now */
6463   k->header = TRUE; /* assume header */
6464 
6465   k->bytecount = 0;
6466 
6467   k->buf = data->state.buffer;
6468   k->uploadbuf = data->state.uploadbuffer;
6469   k->hbufp = data->state.headerbuff;
6470   k->ignorebody=FALSE;
6471 
6472   Curl_speedinit(data);
6473 
6474   Curl_pgrsSetUploadCounter(data, 0);
6475   Curl_pgrsSetDownloadCounter(data, 0);
6476 
6477   return CURLE_OK;
6478 }
6479 
6480 /*
6481 * get_protocol_family()
6482 *
6483 * This is used to return the protocol family for a given protocol.
6484 *
6485 * Parameters:
6486 *
6487 * protocol  [in]  - A single bit protocol identifier such as HTTP or HTTPS.
6488 *
6489 * Returns the family as a single bit protocol identifier.
6490 */
6491 
get_protocol_family(unsigned int protocol)6492 unsigned int get_protocol_family(unsigned int protocol)
6493 {
6494   unsigned int family;
6495 
6496   switch(protocol) {
6497   case CURLPROTO_HTTP:
6498   case CURLPROTO_HTTPS:
6499     family = CURLPROTO_HTTP;
6500     break;
6501 
6502   case CURLPROTO_FTP:
6503   case CURLPROTO_FTPS:
6504     family = CURLPROTO_FTP;
6505     break;
6506 
6507   case CURLPROTO_SCP:
6508     family = CURLPROTO_SCP;
6509     break;
6510 
6511   case CURLPROTO_SFTP:
6512     family = CURLPROTO_SFTP;
6513     break;
6514 
6515   case CURLPROTO_TELNET:
6516     family = CURLPROTO_TELNET;
6517     break;
6518 
6519   case CURLPROTO_LDAP:
6520   case CURLPROTO_LDAPS:
6521     family = CURLPROTO_LDAP;
6522     break;
6523 
6524   case CURLPROTO_DICT:
6525     family = CURLPROTO_DICT;
6526     break;
6527 
6528   case CURLPROTO_FILE:
6529     family = CURLPROTO_FILE;
6530     break;
6531 
6532   case CURLPROTO_TFTP:
6533     family = CURLPROTO_TFTP;
6534     break;
6535 
6536   case CURLPROTO_IMAP:
6537   case CURLPROTO_IMAPS:
6538     family = CURLPROTO_IMAP;
6539     break;
6540 
6541   case CURLPROTO_POP3:
6542   case CURLPROTO_POP3S:
6543     family = CURLPROTO_POP3;
6544     break;
6545 
6546   case CURLPROTO_SMTP:
6547   case CURLPROTO_SMTPS:
6548       family = CURLPROTO_SMTP;
6549       break;
6550 
6551   case CURLPROTO_RTSP:
6552     family = CURLPROTO_RTSP;
6553     break;
6554 
6555   case CURLPROTO_RTMP:
6556   case CURLPROTO_RTMPS:
6557     family = CURLPROTO_RTMP;
6558     break;
6559 
6560   case CURLPROTO_RTMPT:
6561   case CURLPROTO_RTMPTS:
6562     family = CURLPROTO_RTMPT;
6563     break;
6564 
6565   case CURLPROTO_RTMPE:
6566     family = CURLPROTO_RTMPE;
6567     break;
6568 
6569   case CURLPROTO_RTMPTE:
6570     family = CURLPROTO_RTMPTE;
6571     break;
6572 
6573   case CURLPROTO_GOPHER:
6574     family = CURLPROTO_GOPHER;
6575     break;
6576 
6577   case CURLPROTO_SMB:
6578   case CURLPROTO_SMBS:
6579     family = CURLPROTO_SMB;
6580     break;
6581 
6582   default:
6583       family = 0;
6584       break;
6585   }
6586 
6587   return family;
6588 }
6589