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