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