~ubuntu-branches/ubuntu/dapper/curl/dapper-security

« back to all changes in this revision

Viewing changes to lib/url.c

  • Committer: Bazaar Package Importer
  • Author(s): Domenico Andreoli
  • Date: 2004-06-04 19:09:25 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040604190925-wy048bp31320r2z6
Tags: 7.12.0.is.7.11.2-1
* Reverted to version 7.11.2 (closes: #252348).
* Disabled support for libidn (closes: #252367). This is to leave
  curl in unstable as much similar as possible to the one in testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 *                                  _   _ ____  _     
3
 
 *  Project                     ___| | | |  _ \| |    
4
 
 *                             / __| | | | |_) | |    
5
 
 *                            | (__| |_| |  _ <| |___ 
 
1
/***************************************************************************
 
2
 *                                  _   _ ____  _
 
3
 *  Project                     ___| | | |  _ \| |
 
4
 *                             / __| | | | |_) | |
 
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
 
 * In order to be useful for every potential user, curl and libcurl are
11
 
 * dual-licensed under the MPL and the MIT/X-derivate licenses.
 
10
 * This software is licensed as described in the file COPYING, which
 
11
 * you should have received as part of this distribution. The terms
 
12
 * are also available at http://curl.haxx.se/docs/copyright.html.
12
13
 *
13
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
14
15
 * copies of the Software, and permit persons to whom the Software is
15
 
 * furnished to do so, under the terms of the MPL or the MIT/X-derivate
16
 
 * licenses. You may pick one of these licenses.
 
16
 * furnished to do so, under the terms of the COPYING file.
17
17
 *
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: url.c,v 1.191 2002/02/28 23:31:23 bagder Exp $
22
 
 *****************************************************************************/
 
21
 * $Id: url.c,v 1.359 2004/04/21 11:15:02 bagder Exp $
 
22
 ***************************************************************************/
23
23
 
24
24
/* -- WIN32 approved -- */
25
25
 
36
36
#include <errno.h>
37
37
 
38
38
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
39
 
#include <winsock.h>
40
39
#include <time.h>
41
40
#include <io.h>
42
41
#else
45
44
#endif
46
45
#include <netinet/in.h>
47
46
#include <sys/time.h>
48
 
#include <sys/resource.h>
49
47
#ifdef HAVE_UNISTD_H
50
48
#include <unistd.h>
51
49
#endif
67
65
#include <sys/select.h>
68
66
#endif
69
67
 
70
 
#ifdef  VMS
 
68
#ifdef VMS
71
69
#include <in.h>
72
70
#include <inet.h>
73
71
#endif
74
72
 
 
73
#ifdef HAVE_SETJMP_H
 
74
#include <setjmp.h>
 
75
#endif
 
76
 
75
77
#ifndef HAVE_SELECT
76
78
#error "We can't compile without select() support!"
77
79
#endif
79
81
#error "We can't compile without socket() support!"
80
82
#endif
81
83
 
82
 
#endif
83
 
 
 
84
 
 
85
#endif
 
86
 
 
87
#ifdef HAVE_OPENSSL_ENGINE_H
 
88
#include <openssl/engine.h>
 
89
#endif
84
90
#include "urldata.h"
85
91
#include "netrc.h"
86
92
 
91
97
#include "if2ip.h"
92
98
#include "transfer.h"
93
99
#include "sendf.h"
94
 
#include "getpass.h"
95
100
#include "progress.h"
96
101
#include "cookie.h"
97
102
#include "strequal.h"
98
103
#include "escape.h"
99
104
#include "strtok.h"
 
105
#include "share.h"
 
106
#include "content_encoding.h"
 
107
#include "http_digest.h"
 
108
#include "http_negotiate.h"
100
109
 
101
110
/* And now for the protocols */
102
111
#include "ftp.h"
107
116
#include "ldap.h"
108
117
#include "url.h"
109
118
#include "connect.h"
 
119
#include <ca-bundle.h>
110
120
 
111
121
#include <curl/types.h>
112
122
 
117
127
#define _MPRINTF_REPLACE /* use our functions only */
118
128
#include <curl/mprintf.h>
119
129
 
120
 
#ifdef KRB4
 
130
#ifdef HAVE_KRB4
121
131
#include "security.h"
122
132
#endif
 
133
 
123
134
/* The last #include file should be: */
124
 
#ifdef MALLOCDEBUG
 
135
#ifdef CURLDEBUG
125
136
#include "memdebug.h"
126
137
#endif
127
138
 
132
143
                             struct connectdata **usethis);
133
144
static unsigned int ConnectionStore(struct SessionHandle *data,
134
145
                                    struct connectdata *conn);
135
 
 
136
 
 
137
 
#if !defined(WIN32)||defined(__CYGWIN32__)
 
146
static bool safe_strequal(char* str1, char* str2);
 
147
 
 
148
#ifndef USE_ARES
 
149
/* not for Win32, unless it is cygwin
 
150
   not for ares builds */
 
151
#if !defined(WIN32) || defined(__CYGWIN32__)
 
152
 
138
153
#ifndef RETSIGTYPE
139
154
#define RETSIGTYPE void
140
155
#endif
 
156
#ifdef HAVE_SIGSETJMP
 
157
extern sigjmp_buf curl_jmpenv;
 
158
#endif
141
159
static
142
 
RETSIGTYPE alarmfunc(int signal)
 
160
RETSIGTYPE alarmfunc(int sig)
143
161
{
144
162
  /* this is for "-ansi -Wall -pedantic" to stop complaining!   (rabe) */
145
 
  (void)signal;
 
163
  (void)sig;
 
164
#ifdef HAVE_SIGSETJMP
 
165
  siglongjmp(curl_jmpenv, 1);
 
166
#endif
146
167
  return;
147
168
}
148
169
#endif
 
170
#endif /* USE_ARES */
149
171
 
 
172
void Curl_safefree(void *ptr)
 
173
{
 
174
  if(ptr)
 
175
    free(ptr);
 
176
}
150
177
 
151
178
/*
152
179
 * This is the internal function curl_easy_cleanup() calls. This should
167
194
  Curl_SSL_Close_All(data);
168
195
#endif
169
196
 
170
 
  if(data->state.auth_host)
171
 
    free(data->state.auth_host);
 
197
  if(data->change.cookielist) /* clean up list if any */
 
198
    curl_slist_free_all(data->change.cookielist);
 
199
 
 
200
  Curl_safefree(data->state.auth_host);
 
201
  Curl_safefree(data->state.scratch);
172
202
 
173
203
  if(data->change.proxy_alloc)
174
204
    free(data->change.proxy);
179
209
  if(data->change.url_alloc)
180
210
    free(data->change.url);
181
211
 
182
 
  if(data->state.headerbuff)
183
 
    free(data->state.headerbuff);
 
212
  Curl_safefree(data->state.headerbuff);
184
213
 
185
 
  if(data->set.cookiejar)
 
214
#ifndef CURL_DISABLE_HTTP
 
215
  Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
 
216
  if(data->set.cookiejar) {
186
217
    /* we have a "destination" for all the cookies to get dumped to */
187
 
    Curl_cookie_output(data->cookies, data->set.cookiejar);
188
 
    
189
 
  Curl_cookie_cleanup(data->cookies);
 
218
    if(Curl_cookie_output(data->cookies, data->set.cookiejar))
 
219
      infof(data, "WARNING: failed to save cookies in %s\n",
 
220
            data->set.cookiejar);
 
221
  }
 
222
 
 
223
  if( !data->share || (data->cookies != data->share->cookies) ) {
 
224
    Curl_cookie_cleanup(data->cookies);
 
225
  }
 
226
  Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
 
227
#endif
190
228
 
191
229
  /* free the connection cache */
192
230
  free(data->state.connects);
193
231
 
194
 
  if(data->info.contenttype)
195
 
    free(data->info.contenttype);
 
232
  Curl_safefree(data->info.contenttype);
 
233
 
 
234
  Curl_digest_cleanup(data);
 
235
 
 
236
#ifdef USE_ARES
 
237
  /* this destroys the channel and we cannot use it anymore after this */
 
238
  ares_destroy(data->state.areschannel);
 
239
#endif
 
240
 
 
241
  /* No longer a dirty share, if it exists */
 
242
  if (data->share)
 
243
    data->share->dirty--;
196
244
 
197
245
  free(data);
198
246
  return CURLE_OK;
199
247
}
200
248
 
201
 
static
202
 
int my_getpass(void *clientp, const char *prompt, char* buffer, int buflen )
203
 
{
204
 
  char *retbuf;
205
 
  clientp=NULL; /* prevent compiler warning */
206
 
 
207
 
  retbuf = getpass_r(prompt, buffer, buflen);
208
 
  if(NULL == retbuf)
209
 
    return 1;
210
 
  else
211
 
    return 0; /* success */
212
 
}
213
 
 
 
249
/**
 
250
 * Curl_open()
 
251
 *
 
252
 * @param curl is a pointer to a sessionhandle pointer that gets set by this
 
253
 * function.
 
254
 * @return CURLcode
 
255
 */
214
256
 
215
257
CURLcode Curl_open(struct SessionHandle **curl)
216
258
{
221
263
  if(!data)
222
264
    /* this is a very serious error */
223
265
    return CURLE_OUT_OF_MEMORY;
224
 
  
 
266
 
225
267
  memset(data, 0, sizeof(struct SessionHandle));
226
268
 
 
269
#ifdef USE_ARES
 
270
  if(ARES_SUCCESS != ares_init(&data->state.areschannel)) {
 
271
    free(data);
 
272
    return CURLE_FAILED_INIT;
 
273
  }
 
274
  /* make sure that all other returns from this function should destroy the
 
275
     ares channel before returning error! */
 
276
#endif
 
277
 
227
278
  /* We do some initial setup here, all those fields that can't be just 0 */
228
279
 
229
280
  data->state.headerbuff=(char*)malloc(HEADERSIZE);
237
288
  data->set.out = stdout; /* default output to stdout */
238
289
  data->set.in  = stdin;  /* default input from stdin */
239
290
  data->set.err  = stderr;  /* default stderr to stderr */
240
 
  
 
291
 
241
292
  /* use fwrite as default function to store output */
242
293
  data->set.fwrite = (curl_write_callback)fwrite;
243
294
 
244
295
  /* use fread as default function to read input */
245
296
  data->set.fread = (curl_read_callback)fread;
246
 
  
247
 
  /* set the default passwd function */
248
 
  data->set.fpasswd = my_getpass;
249
297
 
250
298
  data->set.infilesize = -1; /* we don't know any size */
251
299
 
253
301
 
254
302
  data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
255
303
  data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
 
304
  data->set.ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
256
305
 
257
306
  data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
258
 
  
 
307
 
259
308
  /* make libcurl quiet by default: */
260
309
  data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
261
310
  data->progress.flags |= PGRS_HIDE;
262
311
 
263
312
  /* Set the default size of the SSL session ID cache */
264
313
  data->set.ssl.numsessions = 5;
265
 
  
 
314
 
 
315
  data->set.proxyport = 1080;
 
316
 
 
317
  data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
 
318
 
 
319
  data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic authentication */
 
320
  data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic authentication */
 
321
 
266
322
  /* create an array with connection data struct pointers */
267
323
  data->state.numconnects = 5; /* hard-coded right now */
268
324
  data->state.connects = (struct connectdata **)
269
325
    malloc(sizeof(struct connectdata *) * data->state.numconnects);
270
 
  
 
326
 
271
327
  if(!data->state.connects) {
 
328
    free(data->state.headerbuff);
272
329
    free(data);
273
330
    return CURLE_OUT_OF_MEMORY;
274
331
  }
275
 
  
 
332
 
 
333
  /*
 
334
   * libcurl 7.10 introduces SSL verification *by default*! This needs to be
 
335
   * switched off unless wanted.
 
336
   */
 
337
  data->set.ssl.verifypeer = TRUE;
 
338
  data->set.ssl.verifyhost = 2;
 
339
#ifdef CURL_CA_BUNDLE
 
340
  /* This is our prefered CA cert bundle since install time */
 
341
  data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
 
342
#endif
 
343
 
276
344
  memset(data->state.connects, 0,
277
345
         sizeof(struct connectdata *)*data->state.numconnects);
278
346
 
279
347
  *curl = data;
280
 
 
281
348
  return CURLE_OK;
282
349
}
283
350
 
292
359
  case CURLOPT_DNS_CACHE_TIMEOUT:
293
360
    data->set.dns_cache_timeout = va_arg(param, int);
294
361
    break;
295
 
  case CURLOPT_DNS_USE_GLOBAL_CACHE: 
 
362
  case CURLOPT_DNS_USE_GLOBAL_CACHE:
296
363
    {
297
364
      int use_cache = va_arg(param, int);
298
365
      if (use_cache) {
338
405
          Curl_disconnect(data->state.connects[i]);
339
406
      }
340
407
      if(newconnects) {
 
408
        int i;
341
409
        newptr= (struct connectdata **)
342
410
          realloc(data->state.connects,
343
411
                  sizeof(struct connectdata *) * newconnects);
344
412
        if(!newptr)
345
413
          /* we closed a few connections in vain, but so what? */
346
414
          return CURLE_OUT_OF_MEMORY;
 
415
 
 
416
        /* nullify the newly added pointers */
 
417
        for(i=data->state.numconnects; i<newconnects; i++) {
 
418
          newptr[i] = NULL;
 
419
        }
 
420
 
347
421
        data->state.connects = newptr;
348
422
        data->state.numconnects = newconnects;
349
423
      }
381
455
    /*
382
456
     * Set to include the header in the general data output stream.
383
457
     */
384
 
    data->set.http_include_header = va_arg(param, long)?TRUE:FALSE;
 
458
    data->set.include_header = va_arg(param, long)?TRUE:FALSE;
385
459
    break;
386
460
  case CURLOPT_NOPROGRESS:
387
461
    /*
397
471
    /*
398
472
     * Do not include the body part in the output data stream.
399
473
     */
400
 
    data->set.no_body = va_arg(param, long)?TRUE:FALSE;
 
474
    data->set.opt_no_body = va_arg(param, long)?TRUE:FALSE;
401
475
    break;
402
476
  case CURLOPT_FAILONERROR:
403
477
    /*
422
496
     */
423
497
    data->set.get_filetime = va_arg(param, long)?TRUE:FALSE;
424
498
    break;
 
499
  case CURLOPT_FTP_CREATE_MISSING_DIRS:
 
500
    /*
 
501
     * An FTP option that modifies an upload to create missing directories on
 
502
     * the server.
 
503
     */ 
 
504
    data->set.ftp_create_missing_dirs = va_arg( param , long )?TRUE:FALSE;
 
505
    break;
 
506
  case CURLOPT_FTP_RESPONSE_TIMEOUT:
 
507
    /*
 
508
     * An FTP option that specifies how quickly an FTP response must be 
 
509
     * obtained before it is considered failure.
 
510
     */
 
511
    data->set.ftp_response_timeout = va_arg( param , long );
 
512
    break;
425
513
  case CURLOPT_FTPLISTONLY:
426
514
    /*
427
515
     * An FTP option that changes the command to one that asks for a list
439
527
    /*
440
528
     * Parse the $HOME/.netrc file
441
529
     */
442
 
    data->set.use_netrc = va_arg(param, long)?TRUE:FALSE;
 
530
    data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
 
531
    break;
 
532
  case CURLOPT_NETRC_FILE:
 
533
    /*
 
534
     * Use this file instead of the $HOME/.netrc file
 
535
     */
 
536
    data->set.netrc_file = va_arg(param, char *);
443
537
    break;
444
538
  case CURLOPT_FOLLOWLOCATION:
445
539
    /*
447
541
     */
448
542
    data->set.http_follow_location = va_arg(param, long)?TRUE:FALSE;
449
543
    break;
 
544
  case CURLOPT_UNRESTRICTED_AUTH:
 
545
    /*
 
546
     * Send authentication (user+password) when following locations, even when
 
547
     * hostname changed.
 
548
     */
 
549
    data->set.http_disable_hostname_check_before_authentication =
 
550
      va_arg(param, long)?TRUE:FALSE;
 
551
    break;
450
552
  case CURLOPT_HTTP_VERSION:
451
553
    /*
452
554
     * This sets a requested HTTP version to be used. The value is one of
476
578
     * Set HTTP time condition. This must be one of the defines in the
477
579
     * curl/curl.h header file.
478
580
     */
479
 
    data->set.timecondition = va_arg(param, long);
 
581
    data->set.timecondition = (curl_TimeCond)va_arg(param, long);
480
582
    break;
481
583
  case CURLOPT_TIMEVALUE:
482
584
    /*
493
595
    data->set.ssl.version = va_arg(param, long);
494
596
    break;
495
597
 
 
598
  case CURLOPT_COOKIESESSION:
 
599
    /*
 
600
     * Set this option to TRUE to start a new "cookie session". It will
 
601
     * prevent the forthcoming read-cookies-from-file actions to accept
 
602
     * cookies that are marked as being session cookies, as they belong to a
 
603
     * previous session.
 
604
     *
 
605
     * In the original Netscape cookie spec, "session cookies" are cookies
 
606
     * with no expire date set. RFC2109 describes the same action if no
 
607
     * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
 
608
     * a 'Discard' action that can enforce the discard even for cookies that
 
609
     * have a Max-Age.
 
610
     *
 
611
     * We run mostly with the original cookie spec, as hardly anyone implements
 
612
     * anything else.
 
613
     */
 
614
    data->set.cookiesession = (bool)va_arg(param, long);
 
615
    break;
 
616
 
 
617
#ifndef CURL_DISABLE_HTTP
496
618
  case CURLOPT_COOKIEFILE:
497
619
    /*
498
620
     * Set cookie file to read and parse. Can be used multiple times.
499
621
     */
500
622
    cookiefile = (char *)va_arg(param, void *);
501
623
    if(cookiefile)
502
 
      data->cookies = Curl_cookie_init(cookiefile, data->cookies);
 
624
      /* append the cookie file name to the list of file names, and deal with
 
625
         them later */
 
626
      data->change.cookielist =
 
627
        curl_slist_append(data->change.cookielist, cookiefile);
503
628
    break;
504
629
 
505
630
  case CURLOPT_COOKIEJAR:
512
637
     * Activate the cookie parser. This may or may not already
513
638
     * have been made.
514
639
     */
515
 
    data->cookies = Curl_cookie_init(NULL, data->cookies);
 
640
    data->cookies = Curl_cookie_init(data, NULL, data->cookies,
 
641
                                     data->set.cookiesession);
516
642
    break;
 
643
#endif
 
644
 
517
645
  case CURLOPT_WRITEHEADER:
518
646
    /*
519
647
     * Custom pointer to pass the header write callback function
547
675
    data->set.ftp_use_port = data->set.ftpport?1:0;
548
676
    break;
549
677
 
 
678
  case CURLOPT_FTP_USE_EPRT:
 
679
    data->set.ftp_use_eprt = va_arg(param, long)?TRUE:FALSE;
 
680
    break;
 
681
 
550
682
  case CURLOPT_FTP_USE_EPSV:
551
683
    data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
552
684
    break;
553
 
 
 
685
    
554
686
  case CURLOPT_HTTPHEADER:
555
687
    /*
556
688
     * Set a list with HTTP headers to use (or replace internals with)
572
704
    /*
573
705
     * Set to make us do HTTP POST
574
706
     */
575
 
    data->set.httppost = va_arg(param, struct HttpPost *);
 
707
    data->set.httppost = va_arg(param, struct curl_httppost *);
576
708
    if(data->set.httppost)
577
709
      data->set.httpreq = HTTPREQ_POST_FORM;
578
710
    break;
601
733
     */
602
734
    data->set.infilesize = va_arg(param, long);
603
735
    break;
 
736
  case CURLOPT_INFILESIZE_LARGE:
 
737
    /*
 
738
     * If known, this should inform curl about the file size of the
 
739
     * to-be-uploaded file.
 
740
     */
 
741
    data->set.infilesize = va_arg(param, curl_off_t);
 
742
    break;
604
743
  case CURLOPT_LOW_SPEED_LIMIT:
605
744
    /*
606
745
     * The low speed limit that if transfers are below this for
626
765
    }
627
766
    data->set.set_url = va_arg(param, char *);
628
767
    data->change.url = data->set.set_url;
 
768
    data->change.url_changed = TRUE;
629
769
    break;
630
770
  case CURLOPT_PORT:
631
771
    /*
634
774
    data->set.use_port = va_arg(param, long);
635
775
    break;
636
776
  case CURLOPT_POST:
637
 
    /* Does this option serve a purpose anymore? */
638
 
 
 
777
    /* Does this option serve a purpose anymore? Yes it does, when
 
778
       CURLOPT_POSTFIELDS isn't used and the POST data is read off the
 
779
       callback! */
639
780
    if(va_arg(param, long))
640
781
      data->set.httpreq = HTTPREQ_POST;
641
782
    break;
649
790
    break;
650
791
  case CURLOPT_POSTFIELDSIZE:
651
792
    /*
652
 
     * The size of the POSTFIELD data, if curl should now do a strlen
653
 
     * to find out. Enables binary posts.
 
793
     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
 
794
     * figure it out. Enables binary posts.
654
795
     */
655
796
    data->set.postfieldsize = va_arg(param, long);
656
797
    break;
 
798
  case CURLOPT_POSTFIELDSIZE_LARGE:
 
799
    /*
 
800
     * The size of the POSTFIELD data to prevent libcurl to do strlen() to
 
801
     * figure it out. Enables binary posts.
 
802
     */
 
803
    data->set.postfieldsize = va_arg(param, curl_off_t);
 
804
    break;
657
805
  case CURLOPT_REFERER:
658
806
    /*
659
807
     * String to set in the HTTP Referer: field.
673
821
    break;
674
822
  case CURLOPT_PROXY:
675
823
    /*
676
 
     * Set proxy server:port to use as HTTP proxy
 
824
     * Set proxy server:port to use as HTTP proxy.
 
825
     *
 
826
     * If the proxy is set to "" we explicitly say that we don't want to use a
 
827
     * proxy (even though there might be environment variables saying so).
 
828
     *
 
829
     * Setting it to NULL, means no proxy but allows the environment variables
 
830
     * to decide for us.
677
831
     */
678
832
    if(data->change.proxy_alloc) {
679
833
      /*
723
877
     */
724
878
    data->set.useragent = va_arg(param, char *);
725
879
    break;
 
880
  case CURLOPT_ENCODING:
 
881
    /*
 
882
     * String to use at the value of Accept-Encoding header. 08/28/02 jhrg
 
883
     *
 
884
     * If the encoding is set to "" we use an Accept-Encoding header that
 
885
     * encompasses all the encodings we support.
 
886
     * If the encoding is set to NULL we don't send an Accept-Encoding header
 
887
     * and ignore an received Content-Encoding header.
 
888
     *
 
889
     */
 
890
    data->set.encoding = va_arg(param, char *);
 
891
    if(data->set.encoding && !*data->set.encoding)
 
892
      data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
 
893
    break;
 
894
 
 
895
  case CURLOPT_HTTPAUTH:
 
896
    /*
 
897
     * Set HTTP Authentication type BITMASK.
 
898
     */
 
899
  {
 
900
    long auth = va_arg(param, long);
 
901
    /* switch off bits we can't support */
 
902
#ifndef USE_SSLEAY
 
903
    auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
 
904
#endif
 
905
#ifndef HAVE_GSSAPI
 
906
    auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
 
907
#endif
 
908
    if(!auth)
 
909
      return CURLE_FAILED_INIT; /* no supported types left! */
 
910
 
 
911
    data->set.httpauth = auth;
 
912
  }
 
913
  break;
 
914
  
 
915
  case CURLOPT_PROXYAUTH:
 
916
    /*
 
917
     * Set HTTP Authentication type BITMASK.
 
918
     */
 
919
  {
 
920
    long auth = va_arg(param, long);
 
921
    /* switch off bits we can't support */
 
922
#ifndef USE_SSLEAY
 
923
    auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
 
924
#endif
 
925
#ifndef HAVE_GSSAPI
 
926
    auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
 
927
#endif
 
928
    if(!auth)
 
929
      return CURLE_FAILED_INIT; /* no supported types left! */
 
930
 
 
931
    data->set.proxyauth = auth;
 
932
  }
 
933
  break;
 
934
 
726
935
  case CURLOPT_USERPWD:
727
936
    /*
728
937
     * user:password to use in the operation
731
940
    break;
732
941
  case CURLOPT_POSTQUOTE:
733
942
    /*
734
 
     * List of RAW FTP commands to use after a transfer 
 
943
     * List of RAW FTP commands to use after a transfer
735
944
     */
736
945
    data->set.postquote = va_arg(param, struct curl_slist *);
737
946
    break;
743
952
    break;
744
953
  case CURLOPT_QUOTE:
745
954
    /*
746
 
     * List of RAW FTP commands to use before a transfer 
 
955
     * List of RAW FTP commands to use before a transfer
747
956
     */
748
957
    data->set.quote = va_arg(param, struct curl_slist *);
749
958
    break;
752
961
     * Progress callback function
753
962
     */
754
963
    data->set.fprogress = va_arg(param, curl_progress_callback);
755
 
    data->progress.callback = TRUE; /* no longer internal */
 
964
    if(data->set.fprogress)
 
965
      data->progress.callback = TRUE; /* no longer internal */
 
966
    else
 
967
      data->progress.callback = FALSE; /* NULL enforces internal */
 
968
 
756
969
    break;
757
970
  case CURLOPT_PROGRESSDATA:
758
971
    /*
760
973
     */
761
974
    data->set.progress_client = va_arg(param, void *);
762
975
    break;
763
 
  case CURLOPT_PASSWDFUNCTION:
764
 
    /*
765
 
     * Password prompt callback
766
 
     */
767
 
    data->set.fpasswd = va_arg(param, curl_passwd_callback);
768
 
    break;
769
 
  case CURLOPT_PASSWDDATA:
770
 
    /*
771
 
     * Custom client data to pass to the password callback
772
 
     */
773
 
    data->set.passwd_client = va_arg(param, void *);
774
 
    break;
775
976
  case CURLOPT_PROXYUSERPWD:
776
977
    /*
777
978
     * user:password needed to use the proxy
790
991
     */
791
992
    data->set.set_resume_from = va_arg(param, long);
792
993
    break;
 
994
  case CURLOPT_RESUME_FROM_LARGE:
 
995
    /*
 
996
     * Resume transfer at the give file position
 
997
     */
 
998
    data->set.set_resume_from = va_arg(param, curl_off_t);
 
999
    break;
 
1000
  case CURLOPT_DEBUGFUNCTION:
 
1001
    /*
 
1002
     * stderr write callback.
 
1003
     */
 
1004
    data->set.fdebug = va_arg(param, curl_debug_callback);
 
1005
    /*
 
1006
     * if the callback provided is NULL, it'll use the default callback
 
1007
     */
 
1008
    break;
 
1009
  case CURLOPT_DEBUGDATA:
 
1010
    /*
 
1011
     * Set to a void * that should receive all error writes. This
 
1012
     * defaults to CURLOPT_STDERR for normal operations.
 
1013
     */
 
1014
    data->set.debugdata = va_arg(param, void *);
 
1015
    break;
793
1016
  case CURLOPT_STDERR:
794
1017
    /*
795
1018
     * Set to a FILE * that should receive all error writes. This
796
1019
     * defaults to stderr for normal operations.
797
1020
     */
798
1021
    data->set.err = va_arg(param, FILE *);
 
1022
    if(!data->set.err)
 
1023
      data->set.err = stderr;
799
1024
    break;
800
1025
  case CURLOPT_HEADERFUNCTION:
801
1026
    /*
808
1033
     * Set data write callback
809
1034
     */
810
1035
    data->set.fwrite = va_arg(param, curl_write_callback);
 
1036
    if(!data->set.fwrite)
 
1037
      /* When set to NULL, reset to our internal default function */
 
1038
      data->set.fwrite = (curl_write_callback)fwrite;
811
1039
    break;
812
1040
  case CURLOPT_READFUNCTION:
813
1041
    /*
814
1042
     * Read data callback
815
1043
     */
816
1044
    data->set.fread = va_arg(param, curl_read_callback);
 
1045
    if(!data->set.fread)
 
1046
      /* When set to NULL, reset to our internal default function */
 
1047
      data->set.fread = (curl_read_callback)fread;
817
1048
    break;
818
1049
  case CURLOPT_SSLCERT:
819
1050
    /*
867
1098
        }
868
1099
      }
869
1100
    }
 
1101
    break;
870
1102
#else
871
1103
    return CURLE_SSL_ENGINE_NOTFOUND;
872
1104
#endif
873
 
    break;
874
1105
  case CURLOPT_SSLENGINE_DEFAULT:
875
1106
    /*
876
1107
     * flag to set engine as default.
923
1154
     */
924
1155
    data->set.ssl.verifyhost = va_arg(param, long);
925
1156
    break;
 
1157
  case CURLOPT_SSL_CTX_FUNCTION:
 
1158
    /*
 
1159
     * Set a SSL_CTX callback
 
1160
     */
 
1161
       data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
 
1162
    break;
 
1163
  case CURLOPT_SSL_CTX_DATA:
 
1164
    /*
 
1165
     * Set a SSL_CTX callback parameter pointer
 
1166
     */
 
1167
    data->set.ssl.fsslctxp = va_arg(param, void *);
 
1168
    break;
926
1169
  case CURLOPT_CAINFO:
927
1170
    /*
928
1171
     * Set CA info for SSL connection. Specify file name of the CA certificate
929
1172
     */
930
1173
    data->set.ssl.CAfile = va_arg(param, char *);
931
 
    data->set.ssl.CApath = NULL; /*This does not work on windows.*/
 
1174
    break;
 
1175
  case CURLOPT_CAPATH:
 
1176
    /*
 
1177
     * Set CA path info for SSL connection. Specify directory name of the CA
 
1178
     * certificates which have been prepared using openssl c_rehash utility.
 
1179
     */
 
1180
    /* This does not work on windows. */
 
1181
    data->set.ssl.CApath = va_arg(param, char *);
932
1182
    break;
933
1183
  case CURLOPT_TELNETOPTIONS:
934
1184
    /*
936
1186
     */
937
1187
    data->set.telnet_options = va_arg(param, struct curl_slist *);
938
1188
    break;
 
1189
 
 
1190
  case CURLOPT_BUFFERSIZE:
 
1191
    /*
 
1192
     * The application kindly asks for a differently sized receive buffer.
 
1193
     * If it seems reasonable, we'll use it.
 
1194
     */
 
1195
    data->set.buffer_size = va_arg(param, long);
 
1196
 
 
1197
    if((data->set.buffer_size> (BUFSIZE -1 )) ||
 
1198
       (data->set.buffer_size < 1))
 
1199
      data->set.buffer_size = 0; /* huge internal default */
 
1200
 
 
1201
    break;
 
1202
 
 
1203
  case CURLOPT_NOSIGNAL:
 
1204
    /*
 
1205
     * The application asks not to set any signal() or alarm() handlers,
 
1206
     * even when using a timeout.
 
1207
     */
 
1208
    data->set.no_signal = va_arg(param, long) ? TRUE : FALSE;
 
1209
    break;
 
1210
 
 
1211
  case CURLOPT_SHARE:
 
1212
    {
 
1213
      struct Curl_share *set;
 
1214
      set = va_arg(param, struct Curl_share *);
 
1215
 
 
1216
      /* disconnect from old share, if any */
 
1217
      if(data->share) {
 
1218
        Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
 
1219
 
 
1220
        if(data->share->hostcache == data->hostcache)
 
1221
          data->hostcache = NULL;
 
1222
 
 
1223
        if(data->share->cookies == data->cookies)
 
1224
          data->cookies = NULL;
 
1225
 
 
1226
        data->share->dirty--;
 
1227
 
 
1228
        Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
 
1229
        data->share = NULL;
 
1230
      }
 
1231
 
 
1232
      /* use new share if it set */
 
1233
      data->share = set;
 
1234
      if(data->share) {
 
1235
 
 
1236
        Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
 
1237
 
 
1238
        data->share->dirty++;
 
1239
 
 
1240
        if(data->share->hostcache) {
 
1241
          /* use shared host cache, first free own one if any */
 
1242
          if(data->hostcache)
 
1243
            Curl_hash_destroy(data->hostcache);
 
1244
 
 
1245
          data->hostcache = data->share->hostcache;
 
1246
        }
 
1247
        
 
1248
        if(data->share->cookies) {
 
1249
          /* use shared cookie list, first free own one if any */
 
1250
          if (data->cookies)
 
1251
            Curl_cookie_cleanup(data->cookies);
 
1252
          data->cookies = data->share->cookies;
 
1253
        }
 
1254
 
 
1255
        Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
 
1256
        
 
1257
      }
 
1258
 
 
1259
      /* check cookie list is set */
 
1260
      if(!data->cookies)
 
1261
        data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE );
 
1262
      
 
1263
      /* check for host cache not needed,
 
1264
       * it will be done by curl_easy_perform */ 
 
1265
    }
 
1266
    break;
 
1267
 
 
1268
  case CURLOPT_PROXYTYPE:
 
1269
    /*
 
1270
     * Set proxy type. HTTP/SOCKS4/SOCKS5
 
1271
     */
 
1272
    data->set.proxytype = (curl_proxytype)va_arg(param, long);
 
1273
    break;
 
1274
 
 
1275
  case CURLOPT_PRIVATE:
 
1276
    /*
 
1277
     * Set private data pointer.
 
1278
     */
 
1279
    data->set.private = va_arg(param, char *);
 
1280
    break;
 
1281
 
 
1282
  case CURLOPT_HTTP200ALIASES:
 
1283
    /*
 
1284
     * Set a list of aliases for HTTP 200 in response header
 
1285
     */
 
1286
    data->set.http200aliases = va_arg(param, struct curl_slist *);
 
1287
    break;
 
1288
 
 
1289
  case CURLOPT_MAXFILESIZE:
 
1290
    /*
 
1291
     * Set the maximum size of a file to download.
 
1292
     */
 
1293
    data->set.max_filesize = va_arg(param, long);
 
1294
    break;
 
1295
 
 
1296
  case CURLOPT_FTP_SSL:
 
1297
    /*
 
1298
     * Make FTP transfers attempt to use SSL/TLS.
 
1299
     */
 
1300
    data->set.ftp_ssl = (curl_ftpssl)va_arg(param, long);
 
1301
    break;
 
1302
 
 
1303
  case CURLOPT_IPRESOLVE:
 
1304
    data->set.ip_version = va_arg(param, long);
 
1305
    break;
 
1306
 
 
1307
  case CURLOPT_MAXFILESIZE_LARGE:
 
1308
    /*
 
1309
     * Set the maximum size of a file to download.
 
1310
     */
 
1311
    data->set.max_filesize = va_arg(param, curl_off_t);
 
1312
    break;
 
1313
 
 
1314
  case CURLOPT_TCP_NODELAY:
 
1315
    /*
 
1316
     * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
 
1317
     * algorithm
 
1318
     */
 
1319
    data->set.tcp_nodelay = (bool)va_arg(param, long);
 
1320
    break;
 
1321
 
939
1322
  default:
940
1323
    /* unknown tag and its companion, just ignore: */
941
 
    return CURLE_READ_ERROR; /* correct this */
 
1324
    return CURLE_FAILED_INIT; /* correct this */
942
1325
  }
943
1326
  return CURLE_OK;
944
1327
}
958
1341
    conn->bits.rangestringalloc = FALSE;
959
1342
  }
960
1343
 
 
1344
  if((conn->ntlm.state != NTLMSTATE_NONE) ||
 
1345
     (conn->proxyntlm.state != NTLMSTATE_NONE))
 
1346
    /* Authentication data is a mix of connection-related and sessionhandle-
 
1347
       related stuff. NTLM is connection-related so when we close the shop
 
1348
       we shall forget. */
 
1349
    conn->data->state.authstage = 0;
 
1350
 
 
1351
  if(conn->curl_disconnect)
 
1352
    /* This is set if protocol-specific cleanups should be made */
 
1353
    conn->curl_disconnect(conn);
 
1354
 
961
1355
  if(-1 != conn->connectindex) {
962
1356
    /* unlink ourselves! */
963
1357
    infof(conn->data, "Closing connection #%d\n", conn->connectindex);
964
1358
    conn->data->state.connects[conn->connectindex] = NULL;
965
1359
  }
966
1360
 
967
 
  if(conn->curl_disconnect)
968
 
    /* This is set if protocol-specific cleanups should be made */
969
 
    conn->curl_disconnect(conn);
970
 
 
971
 
  if(conn->proto.generic)
972
 
    free(conn->proto.generic);
973
 
 
974
 
  if(conn->newurl)
975
 
    free(conn->newurl);
976
 
 
977
 
  if(conn->path) /* the URL path part */
978
 
    free(conn->path);
979
 
 
980
 
#ifdef USE_SSLEAY
 
1361
  Curl_safefree(conn->proto.generic);
 
1362
  Curl_safefree(conn->newurl);
 
1363
  Curl_safefree(conn->pathbuffer); /* the URL path buffer */
 
1364
  Curl_safefree(conn->namebuffer); /* the URL host name buffer */
981
1365
  Curl_SSL_Close(conn);
982
 
#endif /* USE_SSLEAY */
983
1366
 
984
1367
  /* close possibly still open sockets */
985
 
  if(-1 != conn->secondarysocket)
986
 
    sclose(conn->secondarysocket);
987
 
  if(-1 != conn->firstsocket)
988
 
    sclose(conn->firstsocket);
989
 
 
990
 
  if(conn->allocptr.proxyuserpwd)
991
 
    free(conn->allocptr.proxyuserpwd);
992
 
  if(conn->allocptr.uagent)
993
 
    free(conn->allocptr.uagent);
994
 
  if(conn->allocptr.userpwd)
995
 
    free(conn->allocptr.userpwd);
996
 
  if(conn->allocptr.rangeline)
997
 
    free(conn->allocptr.rangeline);
998
 
  if(conn->allocptr.ref)
999
 
    free(conn->allocptr.ref);
1000
 
  if(conn->allocptr.cookie)
1001
 
    free(conn->allocptr.cookie);
1002
 
  if(conn->allocptr.host)
1003
 
    free(conn->allocptr.host);
1004
 
 
1005
 
  if(conn->proxyhost)
1006
 
    free(conn->proxyhost);
 
1368
  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
 
1369
    sclose(conn->sock[SECONDARYSOCKET]);
 
1370
  if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
 
1371
    sclose(conn->sock[FIRSTSOCKET]);
 
1372
 
 
1373
  Curl_safefree(conn->user);
 
1374
  Curl_safefree(conn->passwd);
 
1375
  Curl_safefree(conn->proxyuser);
 
1376
  Curl_safefree(conn->proxypasswd);
 
1377
  Curl_safefree(conn->allocptr.proxyuserpwd);
 
1378
  Curl_safefree(conn->allocptr.uagent);
 
1379
  Curl_safefree(conn->allocptr.userpwd);
 
1380
  Curl_safefree(conn->allocptr.accept_encoding);
 
1381
  Curl_safefree(conn->allocptr.rangeline);
 
1382
  Curl_safefree(conn->allocptr.ref);
 
1383
  Curl_safefree(conn->allocptr.cookie);
 
1384
  Curl_safefree(conn->allocptr.host);
 
1385
  Curl_safefree(conn->allocptr.cookiehost);
 
1386
  Curl_safefree(conn->proxyhost);
 
1387
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME)
 
1388
  /* possible left-overs from the async name resolve */
 
1389
  Curl_safefree(conn->async.hostname);
 
1390
  Curl_safefree(conn->async.os_specific);
 
1391
#endif
 
1392
  
 
1393
  Curl_free_ssl_config(&conn->ssl_config);
1007
1394
 
1008
1395
  free(conn); /* free all the connection oriented data */
1009
1396
 
1015
1402
 * be dead. Most commonly this happens when the server has closed the
1016
1403
 * connection due to inactivity.
1017
1404
 */
1018
 
static bool SocketIsDead(int sock) 
1019
 
1020
 
  int sval; 
1021
 
  bool ret_val = TRUE; 
1022
 
  fd_set check_set; 
1023
 
  struct timeval to; 
1024
 
 
1025
 
  FD_ZERO(&check_set); 
1026
 
  FD_SET(sock,&check_set); 
1027
 
 
1028
 
  to.tv_sec = 0; 
1029
 
  to.tv_usec = 1; 
 
1405
static bool SocketIsDead(curl_socket_t sock)
 
1406
{
 
1407
  int sval;
 
1408
  bool ret_val = TRUE;
 
1409
  fd_set check_set;
 
1410
  struct timeval to;
 
1411
 
 
1412
  FD_ZERO(&check_set);
 
1413
  FD_SET(sock, &check_set);
 
1414
 
 
1415
  to.tv_sec = 0;
 
1416
  to.tv_usec = 0;
1030
1417
 
1031
1418
  sval = select(sock + 1, &check_set, 0, 0, &to);
1032
1419
  if(sval == 0)
1033
1420
    /* timeout */
1034
1421
    ret_val = FALSE;
1035
 
  
 
1422
 
1036
1423
  return ret_val;
1037
1424
}
1038
1425
 
1050
1437
  struct connectdata *check;
1051
1438
 
1052
1439
  for(i=0; i< data->state.numconnects; i++) {
 
1440
    bool match = FALSE;
1053
1441
    /*
1054
1442
     * Note that if we use a HTTP proxy, we check connections to that
1055
1443
     * proxy and not to the actual remote server.
1058
1446
    if(!check)
1059
1447
      /* NULL pointer means not filled-in entry */
1060
1448
      continue;
 
1449
 
 
1450
    if((needle->protocol&PROT_SSL) != (check->protocol&PROT_SSL))
 
1451
      /* don't do mixed SSL and non-SSL connections */
 
1452
      continue;
 
1453
 
1061
1454
    if(!needle->bits.httpproxy || needle->protocol&PROT_SSL) {
1062
1455
      /* The requested connection does not use a HTTP proxy or it
1063
1456
         uses SSL. */
1068
1461
        continue;
1069
1462
 
1070
1463
      if(strequal(needle->protostr, check->protostr) &&
1071
 
         strequal(needle->name, check->name) &&
 
1464
         strequal(needle->hostname, check->hostname) &&
1072
1465
         (needle->remote_port == check->remote_port) ) {
1073
 
        bool dead;
1074
 
        if(strequal(needle->protostr, "FTP")) {
1075
 
          /* This is FTP, verify that we're using the same name and
1076
 
             password as well */
1077
 
          if(!strequal(needle->data->state.user, check->proto.ftp->user) ||
1078
 
             !strequal(needle->data->state.passwd, check->proto.ftp->passwd)) {
 
1466
        if(needle->protocol & PROT_SSL) {
 
1467
          /* This is SSL, verify that we're using the same
 
1468
             ssl options as well */
 
1469
          if(!Curl_ssl_config_matches(&needle->ssl_config,
 
1470
                                      &check->ssl_config)) {
 
1471
            continue;
 
1472
          }
 
1473
        }
 
1474
        if((needle->protocol & PROT_FTP) ||
 
1475
           ((needle->protocol & PROT_HTTP) &&
 
1476
            (needle->data->state.authwant==CURLAUTH_NTLM))) {
 
1477
          /* This is FTP or HTTP+NTLM, verify that we're using the same name
 
1478
             and password as well */
 
1479
          if(!strequal(needle->user, check->user) ||
 
1480
             !strequal(needle->passwd, check->passwd)) {
1079
1481
            /* one of them was different */
1080
1482
            continue;
1081
1483
          }
1082
1484
        }
1083
 
        dead = SocketIsDead(check->firstsocket);
1084
 
        if(dead) {
1085
 
          /*
1086
 
           * Even though the connection seems to have passed away, we could
1087
 
           * still make an effort to get the name information, as we intend to
1088
 
           * connect to the same host again.
1089
 
           *
1090
 
           * This is now subject to discussion. What do you think?
1091
 
           */
1092
 
          infof(data, "Connection %d seems to be dead!\n", i);
1093
 
          Curl_disconnect(check); /* disconnect resources */
1094
 
          data->state.connects[i]=NULL; /* nothing here */
1095
 
 
1096
 
          /* There's no need to continue search, because we only store
1097
 
             one connection for each unique set of identifiers */
1098
 
          return FALSE;
1099
 
        }
1100
 
 
1101
 
        *usethis = check;
1102
 
        return TRUE; /* yes, we found one to use! */
1103
 
        
 
1485
        match = TRUE;
1104
1486
      }
1105
1487
    }
1106
1488
    else { /* The requested needle connection is using a proxy,
1109
1491
         strequal(needle->proxyhost, check->proxyhost) &&
1110
1492
         needle->port == check->port) {
1111
1493
        /* This is the same proxy connection, use it! */
1112
 
        *usethis = check;
1113
 
        return TRUE;
1114
 
      }
 
1494
        match = TRUE;
 
1495
      }
 
1496
    }
 
1497
 
 
1498
    if(match) {
 
1499
      bool dead = SocketIsDead(check->sock[FIRSTSOCKET]);
 
1500
      if(dead) {
 
1501
        /*
 
1502
         */
 
1503
        infof(data, "Connection %d seems to be dead!\n", i);
 
1504
        Curl_disconnect(check); /* disconnect resources */
 
1505
        data->state.connects[i]=NULL; /* nothing here */
 
1506
 
 
1507
        /* There's no need to continue searching, because we only store
 
1508
           one connection for each unique set of identifiers */
 
1509
        return FALSE;
 
1510
      }
 
1511
 
 
1512
      *usethis = check;
 
1513
      return TRUE; /* yes, we found one to use! */
1115
1514
    }
1116
1515
  }
1117
1516
  return FALSE; /* no matching connecting exists */
1130
1529
  int highscore=-1;
1131
1530
  int connindex=-1;
1132
1531
  int score;
1133
 
  CURLcode result;
1134
1532
  struct timeval now;
1135
1533
 
1136
1534
  now = Curl_tvnow();
1137
1535
 
1138
1536
  for(i=0; i< data->state.numconnects; i++) {
1139
1537
    conn = data->state.connects[i];
1140
 
    
 
1538
 
1141
1539
    if(!conn)
1142
1540
      continue;
1143
1541
 
1170
1568
  if(connindex >= 0) {
1171
1569
 
1172
1570
    /* the winner gets the honour of being disconnected */
1173
 
    result = Curl_disconnect(data->state.connects[connindex]);
 
1571
    (void) Curl_disconnect(data->state.connects[connindex]);
1174
1572
 
1175
1573
    /* clean the array entry */
1176
1574
    data->state.connects[connindex] = NULL;
1213
1611
  return i;
1214
1612
}
1215
1613
 
1216
 
static CURLcode ConnectPlease(struct connectdata *conn)
 
1614
/*
 
1615
 * This function logs in to a SOCKS5 proxy and sends the specifies the final
 
1616
 * desitination server.
 
1617
 */
 
1618
static int handleSock5Proxy(const char *proxy_name,
 
1619
                            const char *proxy_password,
 
1620
                            struct connectdata *conn)
 
1621
{
 
1622
  /*
 
1623
    According to the RFC1928, section "6.  Replies". This is what a SOCK5
 
1624
    replies:
 
1625
 
 
1626
        +----+-----+-------+------+----------+----------+
 
1627
        |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
 
1628
        +----+-----+-------+------+----------+----------+
 
1629
        | 1  |  1  | X'00' |  1   | Variable |    2     |
 
1630
        +----+-----+-------+------+----------+----------+
 
1631
 
 
1632
    Where:
 
1633
 
 
1634
    o  VER    protocol version: X'05'
 
1635
    o  REP    Reply field:
 
1636
    o  X'00' succeeded
 
1637
  */
 
1638
 
 
1639
  unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
 
1640
  ssize_t actualread;
 
1641
  ssize_t written;
 
1642
  int result;
 
1643
  CURLcode code;
 
1644
  int sock = conn->sock[FIRSTSOCKET];
 
1645
 
 
1646
  Curl_nonblock(sock, FALSE);
 
1647
 
 
1648
  socksreq[0] = 5; /* version */
 
1649
  socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
 
1650
  socksreq[2] = 0; /* no authentication */
 
1651
  socksreq[3] = 2; /* username/password */
 
1652
 
 
1653
  code = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
 
1654
                      &written);
 
1655
  if ((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
 
1656
    failf(conn->data, "Unable to send initial SOCKS5 request.");
 
1657
    return 1;
 
1658
  }
 
1659
 
 
1660
  result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread);
 
1661
  if ((result != CURLE_OK) || (actualread != 2)) {
 
1662
    failf(conn->data, "Unable to receive initial SOCKS5 response.");
 
1663
    return 1;
 
1664
  }
 
1665
 
 
1666
  if (socksreq[0] != 5) {
 
1667
    failf(conn->data, "Received invalid version in initial SOCKS5 response.");
 
1668
    return 1;
 
1669
  }
 
1670
  if (socksreq[1] == 0) {
 
1671
    /* Nothing to do, no authentication needed */
 
1672
    ;
 
1673
  }
 
1674
  else if (socksreq[1] == 2) {
 
1675
    /* Needs user name and password */
 
1676
    int userlen, pwlen, len;
 
1677
 
 
1678
    userlen = strlen(proxy_name);
 
1679
    pwlen = proxy_password?strlen(proxy_password):0;
 
1680
 
 
1681
    /*   username/password request looks like
 
1682
     * +----+------+----------+------+----------+
 
1683
     * |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
 
1684
     * +----+------+----------+------+----------+
 
1685
     * | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
 
1686
     * +----+------+----------+------+----------+
 
1687
     */
 
1688
    len = 0;
 
1689
    socksreq[len++] = 1;    /* username/pw subnegotiation version */
 
1690
    socksreq[len++] = (char) userlen;
 
1691
    memcpy(socksreq + len, proxy_name, (int) userlen);
 
1692
    len += userlen;
 
1693
    socksreq[len++] = (char) pwlen;
 
1694
    memcpy(socksreq + len, proxy_password, (int) pwlen);
 
1695
    len += pwlen;
 
1696
 
 
1697
    code = Curl_write(conn, sock, (char *)socksreq, len, &written);
 
1698
    if ((code != CURLE_OK) || (len != written)) {
 
1699
      failf(conn->data, "Failed to send SOCKS5 sub-negotiation request.");
 
1700
      return 1;
 
1701
    }
 
1702
 
 
1703
    result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread);
 
1704
    if ((result != CURLE_OK) || (actualread != 2)) {
 
1705
      failf(conn->data, "Unable to receive SOCKS5 sub-negotiation response.");
 
1706
      return 1;
 
1707
    }
 
1708
 
 
1709
    if ((socksreq[0] != 5) || /* version */
 
1710
        (socksreq[1] != 0)) { /* status */
 
1711
      failf(conn->data, "User was rejected by the SOCKS5 server (%d %d).",
 
1712
            socksreq[0], socksreq[1]);
 
1713
      return 1;
 
1714
    }
 
1715
 
 
1716
    /* Everything is good so far, user was authenticated! */
 
1717
  }
 
1718
  else {
 
1719
    /* error */
 
1720
    if (socksreq[1] == 1) {
 
1721
      failf(conn->data,
 
1722
            "SOCKS5 GSSAPI per-message authentication is not supported.");
 
1723
      return 1;
 
1724
    }
 
1725
    else if (socksreq[1] == 255) {
 
1726
      if (proxy_name[0] == 0) {
 
1727
        failf(conn->data,
 
1728
              "No authentication method was acceptable. (It is quite likely"
 
1729
              " that the SOCKS5 server wanted a username/password, since none"
 
1730
              " was supplied to the server on this connection.)");
 
1731
      }
 
1732
      else {
 
1733
        failf(conn->data, "No authentication method was acceptable.");
 
1734
      }
 
1735
      return 1;
 
1736
    }
 
1737
    else {
 
1738
      failf(conn->data,
 
1739
            "Undocumented SOCKS5 mode attempted to be used by server.");
 
1740
      return 1;
 
1741
    }
 
1742
  }
 
1743
 
 
1744
  /* Authentication is complete, now specify destination to the proxy */
 
1745
  socksreq[0] = 5; /* version (SOCKS5) */
 
1746
  socksreq[1] = 1; /* connect */
 
1747
  socksreq[2] = 0; /* must be zero */
 
1748
  socksreq[3] = 1; /* IPv4 = 1 */
 
1749
 
 
1750
  {
 
1751
#ifndef ENABLE_IPV6
 
1752
    struct Curl_dns_entry *dns;
 
1753
    Curl_addrinfo *hp=NULL;
 
1754
    int rc = Curl_resolv(conn, conn->hostname, conn->remote_port, &dns);
 
1755
    
 
1756
    if(rc == -1)
 
1757
      return 1;
 
1758
 
 
1759
    if(rc == 1)
 
1760
      /* this requires that we're in "wait for resolve" state */
 
1761
      rc = Curl_wait_for_resolv(conn, &dns);
 
1762
    
 
1763
    /*
 
1764
     * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
 
1765
     * returns a Curl_addrinfo pointer that may not always look the same.
 
1766
     */
 
1767
    if(dns)
 
1768
      hp=dns->addr;
 
1769
    if (hp && hp->h_addr_list[0]) {
 
1770
      socksreq[4] = ((char*)hp->h_addr_list[0])[0];
 
1771
      socksreq[5] = ((char*)hp->h_addr_list[0])[1];
 
1772
      socksreq[6] = ((char*)hp->h_addr_list[0])[2];
 
1773
      socksreq[7] = ((char*)hp->h_addr_list[0])[3];
 
1774
 
 
1775
      Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */
 
1776
    }
 
1777
    else {
 
1778
      failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.",
 
1779
            conn->hostname);
 
1780
      return 1;
 
1781
    }
 
1782
#else
 
1783
    failf(conn->data,
 
1784
          "%s:%d has an internal error an needs to be fixed to work",
 
1785
          __FILE__, __LINE__);
 
1786
    return 1;
 
1787
#endif
 
1788
  }
 
1789
 
 
1790
  *((unsigned short*)&socksreq[8]) = htons(conn->remote_port);
 
1791
 
 
1792
  {
 
1793
    const int packetsize = 10;
 
1794
 
 
1795
    code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
 
1796
    if ((code != CURLE_OK) || (written != packetsize)) {
 
1797
      failf(conn->data, "Failed to send SOCKS5 connect request.");
 
1798
      return 1;
 
1799
    }
 
1800
 
 
1801
    result = Curl_read(conn, sock, (char *)socksreq, packetsize, &actualread);
 
1802
    if ((result != CURLE_OK) || (actualread != packetsize)) {
 
1803
      failf(conn->data, "Failed to receive SOCKS5 connect request ack.");
 
1804
      return 1;
 
1805
    }
 
1806
 
 
1807
    if (socksreq[0] != 5) { /* version */
 
1808
      failf(conn->data,
 
1809
            "SOCKS5 reply has wrong version, version should be 5.");
 
1810
      return 1;
 
1811
    }
 
1812
    if (socksreq[1] != 0) { /* Anything besides 0 is an error */
 
1813
        failf(conn->data,
 
1814
              "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
 
1815
              (unsigned char)socksreq[4], (unsigned char)socksreq[5],
 
1816
              (unsigned char)socksreq[6], (unsigned char)socksreq[7],
 
1817
              (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
 
1818
              socksreq[1]);
 
1819
        return 1;
 
1820
    }
 
1821
  }
 
1822
 
 
1823
  Curl_nonblock(sock, TRUE);
 
1824
  return 0; /* Proxy was successful! */
 
1825
}
 
1826
 
 
1827
static CURLcode ConnectPlease(struct connectdata *conn,
 
1828
                              struct Curl_dns_entry *hostaddr,
 
1829
                              bool *connected)
1217
1830
{
1218
1831
  CURLcode result;
1219
1832
  Curl_ipconnect *addr;
1222
1835
   * Connect to server/proxy
1223
1836
   *************************************************************/
1224
1837
  result= Curl_connecthost(conn,
1225
 
                           conn->hostaddr,
 
1838
                           hostaddr,
1226
1839
                           conn->port,
1227
 
                           &conn->firstsocket,
1228
 
                           &addr);
 
1840
                           &conn->sock[FIRSTSOCKET],
 
1841
                           &addr,
 
1842
                           connected);
1229
1843
  if(CURLE_OK == result) {
1230
1844
    /* All is cool, then we store the current information from the hostaddr
1231
1845
       struct to the serv_addr, as it might be needed later. The address
1232
1846
       returned from the function above is crucial here. */
 
1847
    conn->connect_addr = hostaddr;
 
1848
 
1233
1849
#ifdef ENABLE_IPV6
1234
1850
    conn->serv_addr = addr;
1235
1851
#else
1236
1852
    memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr));
1237
1853
    memcpy((char *)&(conn->serv_addr.sin_addr),
1238
1854
           (struct in_addr *)addr, sizeof(struct in_addr));
1239
 
    conn->serv_addr.sin_family = conn->hostaddr->h_addrtype;
1240
 
    conn->serv_addr.sin_port = htons(conn->port);
 
1855
    conn->serv_addr.sin_family = hostaddr->addr->h_addrtype;
 
1856
    conn->serv_addr.sin_port = htons((unsigned short)conn->port);
1241
1857
#endif
 
1858
 
 
1859
    if (conn->data->set.proxytype == CURLPROXY_SOCKS5) {
 
1860
      return handleSock5Proxy(conn->proxyuser,
 
1861
                              conn->proxypasswd,
 
1862
                              conn) ?
 
1863
        CURLE_COULDNT_CONNECT : CURLE_OK;
 
1864
    }
 
1865
    else if (conn->data->set.proxytype == CURLPROXY_HTTP) {
 
1866
      /* do nothing here. handled later. */
 
1867
    }
 
1868
    else {
 
1869
      failf(conn->data, "unknown proxytype option given");
 
1870
      return CURLE_COULDNT_CONNECT;
 
1871
    }
1242
1872
  }
1243
1873
 
1244
1874
  return result;
1245
1875
}
1246
1876
 
 
1877
/*
 
1878
 * ALERT! The 'dns' pointer being passed in here might be NULL at times.
 
1879
 */
 
1880
static void verboseconnect(struct connectdata *conn,
 
1881
                           struct Curl_dns_entry *dns)
 
1882
{
 
1883
  struct SessionHandle *data = conn->data;
 
1884
 
 
1885
  /* Figure out the ip-number and display the first host name it shows: */
 
1886
#ifdef ENABLE_IPV6
 
1887
  {
 
1888
    char hbuf[NI_MAXHOST];
 
1889
#ifdef HAVE_NI_WITHSCOPEID
 
1890
#define NIFLAGS NI_NUMERICHOST | NI_WITHSCOPEID
 
1891
#else
 
1892
#define NIFLAGS NI_NUMERICHOST
 
1893
#endif
 
1894
    if(dns) {
 
1895
      struct addrinfo *ai = dns->addr;
 
1896
 
 
1897
      /* Lookup the name of the given address. This should probably be remade
 
1898
         to use the DNS cache instead, as the host name is most likely cached
 
1899
         already. */
 
1900
      if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
 
1901
                      NIFLAGS)) {
 
1902
        snprintf(hbuf, sizeof(hbuf), "unknown");
 
1903
      }
 
1904
      else {
 
1905
        if (ai->ai_canonname) {
 
1906
          infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
 
1907
                conn->port);
 
1908
          return;
 
1909
        }
 
1910
      }
 
1911
    }
 
1912
    else {
 
1913
      snprintf(hbuf, sizeof(hbuf), "same host");
 
1914
    }
 
1915
 
 
1916
    infof(data, "Connected to %s port %d\n", hbuf, conn->port);
 
1917
  }
 
1918
#else
 
1919
  {
 
1920
#ifdef HAVE_INET_NTOA_R
 
1921
    char ntoa_buf[64];
 
1922
#endif
 
1923
    Curl_addrinfo *hostaddr=dns?dns->addr:NULL;
 
1924
    struct in_addr in;
 
1925
    (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
 
1926
    infof(data, "Connected to %s (%s) port %d\n",
 
1927
          hostaddr?hostaddr->h_name:"",
 
1928
#if defined(HAVE_INET_NTOA_R)
 
1929
          inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)),
 
1930
#else
 
1931
          inet_ntoa(in),
 
1932
#endif
 
1933
          conn->port);
 
1934
  }
 
1935
#endif
 
1936
}
 
1937
 
 
1938
/*
 
1939
 * We have discovered that the TCP connection has been successful, we can now
 
1940
 * proceed with some action.
 
1941
 *
 
1942
 * If we're using the multi interface, this host address pointer is most
 
1943
 * likely NULL at this point as we can't keep the resolved info around. This
 
1944
 * may call for some reworking, like a reference counter in the struct or
 
1945
 * something. The hostaddr is not used for very much though, we have the
 
1946
 * 'serv_addr' field in the connectdata struct for most of it.
 
1947
 */
 
1948
CURLcode Curl_protocol_connect(struct connectdata *conn,
 
1949
                               struct Curl_dns_entry *hostaddr)
 
1950
{
 
1951
  struct SessionHandle *data = conn->data;
 
1952
  CURLcode result=CURLE_OK;
 
1953
 
 
1954
  if(conn->bits.tcpconnect)
 
1955
    /* We already are connected, get back. This may happen when the connect
 
1956
       worked fine in the first call, like when we connect to a local server
 
1957
       or proxy. */
 
1958
    return CURLE_OK;
 
1959
 
 
1960
  Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
 
1961
 
 
1962
  if(data->set.verbose)
 
1963
    verboseconnect(conn, hostaddr);
 
1964
 
 
1965
  if(conn->curl_connect) {
 
1966
    /* is there a protocol-specific connect() procedure? */
 
1967
 
 
1968
    /* set start time here for timeout purposes in the
 
1969
     * connect procedure, it is later set again for the
 
1970
     * progress meter purpose */
 
1971
    conn->now = Curl_tvnow();
 
1972
 
 
1973
    /* Call the protocol-specific connect function */
 
1974
    result = conn->curl_connect(conn);
 
1975
  }
 
1976
 
 
1977
  return result; /* pass back status */
 
1978
}
 
1979
 
 
1980
/**
 
1981
 * CreateConnection() sets up a new connectdata struct, or re-uses an already
 
1982
 * existing one, and resolves host name.
 
1983
 *
 
1984
 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
 
1985
 * response will be coming asynchronously. If *async is FALSE, the name is
 
1986
 * already resolved.
 
1987
 *
 
1988
 * @param data The sessionhandle pointer
 
1989
 * @param in_connect is set to the next connection data pointer
 
1990
 * @param addr is set to the new dns entry for this connection
 
1991
 * @param async is set TRUE/FALSE depending on the nature of this lookup
 
1992
 * @return CURLcode
 
1993
 * @see SetupConnection()
 
1994
 */
 
1995
 
1247
1996
static CURLcode CreateConnection(struct SessionHandle *data,
1248
 
                                 struct connectdata **in_connect)
 
1997
                                 struct connectdata **in_connect,
 
1998
                                 struct Curl_dns_entry **addr,
 
1999
                                 bool *async)
1249
2000
{
1250
2001
  char *tmp;
1251
 
  char *buf;
1252
2002
  CURLcode result=CURLE_OK;
1253
2003
  char resumerange[40]="";
1254
2004
  struct connectdata *conn;
1255
2005
  struct connectdata *conn_temp;
 
2006
  int urllen;
 
2007
  struct Curl_dns_entry *hostaddr;
 
2008
#ifdef HAVE_ALARM
 
2009
  unsigned int prev_alarm=0;
 
2010
#endif
1256
2011
  char endbracket;
1257
 
  int urllen;
1258
 
#ifdef HAVE_INET_NTOA_R
1259
 
  char ntoa_buf[64];
1260
 
#endif
1261
 
#ifdef HAVE_ALARM
1262
 
  unsigned int prev_alarm;
1263
 
#endif
 
2012
  char user[MAX_CURL_USER_LENGTH];
 
2013
  char passwd[MAX_CURL_PASSWORD_LENGTH];
 
2014
  int rc;
 
2015
  bool reuse;
1264
2016
 
1265
2017
#ifdef HAVE_SIGACTION
1266
2018
  struct sigaction keep_sigact;   /* store the old struct here */
1267
 
  bool keep_copysig;              /* did copy it? */
 
2019
  bool keep_copysig=FALSE;        /* did copy it? */
1268
2020
#else
1269
2021
#ifdef HAVE_SIGNAL
1270
2022
  void *keep_sigact;              /* store the old handler here */
1271
2023
#endif
1272
2024
#endif
1273
2025
 
 
2026
  *addr = NULL; /* nothing yet */
 
2027
  *async = FALSE;
 
2028
  
1274
2029
  /*************************************************************
1275
2030
   * Check input data
1276
2031
   *************************************************************/
1298
2053
 
1299
2054
  /* and we setup a few fields in case we end up actually using this struct */
1300
2055
  conn->data = data;           /* remember our daddy */
1301
 
  conn->firstsocket = -1;     /* no file descriptor */
1302
 
  conn->secondarysocket = -1; /* no file descriptor */
 
2056
  conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
 
2057
  conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1303
2058
  conn->connectindex = -1;    /* no index */
1304
 
  conn->bits.httpproxy = data->change.proxy?TRUE:FALSE; /* proxy-or-not */
1305
 
  conn->bits.use_range = data->set.set_range?TRUE:FALSE; /* range status */
1306
 
  conn->range = data->set.set_range;               /* clone the range setting */
1307
 
  conn->resume_from = data->set.set_resume_from;   /* inherite resume_from */
 
2059
  conn->bits.httpproxy = (data->change.proxy && *data->change.proxy &&
 
2060
                          (data->set.proxytype == CURLPROXY_HTTP))?
 
2061
    TRUE:FALSE; /* http proxy or not */
1308
2062
 
1309
2063
  /* Default protocol-independent behavior doesn't support persistant
1310
2064
     connections, so we set this to force-close. Protocols that support
1311
2065
     this need to set this to FALSE in their "curl_do" functions. */
1312
2066
  conn->bits.close = TRUE;
1313
 
  
1314
 
  /* inherite initial knowledge from the data struct */
1315
 
  conn->bits.user_passwd = data->set.userpwd?1:0;
1316
 
  conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
1317
2067
 
1318
2068
  /* maxdownload must be -1 on init, as 0 is a valid value! */
1319
2069
  conn->maxdownload = -1;  /* might have been used previously! */
1321
2071
  /* Store creation time to help future close decision making */
1322
2072
  conn->created = Curl_tvnow();
1323
2073
 
 
2074
  conn->bits.use_range = data->set.set_range?TRUE:FALSE; /* range status */
 
2075
  conn->range = data->set.set_range;              /* clone the range setting */
 
2076
  conn->resume_from = data->set.set_resume_from;   /* inherite resume_from */
 
2077
 
 
2078
  /* Set the start time temporary to this creation time to allow easier
 
2079
     timeout checks before the transfer has started for real. The start time
 
2080
     is later set "for real" using Curl_pgrsStartNow(). */
 
2081
  conn->data->progress.start = conn->created;
 
2082
 
 
2083
  conn->bits.user_passwd = data->set.userpwd?1:0;
 
2084
  conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
 
2085
  conn->bits.no_body = data->set.opt_no_body;
 
2086
 
 
2087
  /* This initing continues below, see the comment "Continue connectdata
 
2088
   * initialization here" */
1324
2089
 
1325
2090
  /***********************************************************
1326
2091
   * We need to allocate memory to store the path in. We get the size of the
1331
2096
  urllen=strlen(data->change.url);
1332
2097
  if(urllen < LEAST_PATH_ALLOC)
1333
2098
    urllen=LEAST_PATH_ALLOC;
1334
 
  
1335
 
  conn->path=(char *)malloc(urllen);
1336
 
  if(NULL == conn->path)
 
2099
 
 
2100
  conn->pathbuffer=(char *)malloc(urllen);
 
2101
  if(NULL == conn->pathbuffer)
1337
2102
    return CURLE_OUT_OF_MEMORY; /* really bad error */
 
2103
  conn->path = conn->pathbuffer;
 
2104
 
 
2105
  conn->namebuffer=(char *)malloc(urllen);
 
2106
  if(NULL == conn->namebuffer)
 
2107
    return CURLE_OUT_OF_MEMORY;
 
2108
  conn->hostname = conn->namebuffer;
1338
2109
 
1339
2110
  /*************************************************************
1340
2111
   * Parse the URL.
1344
2115
   * proxy -- and we don't know if we will need to use SSL until we parse the
1345
2116
   * url ...
1346
2117
   ************************************************************/
1347
 
  if((2 == sscanf(data->change.url, "%64[^:]://%[^\n]",
 
2118
  if((2 == sscanf(data->change.url, "%64[^:]:%[^\n]",
1348
2119
                  conn->protostr,
1349
2120
                  conn->path)) && strequal(conn->protostr, "file")) {
 
2121
    if(conn->path[0] == '/' && conn->path[1] == '/') {
 
2122
      /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
 
2123
       * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
 
2124
       * file://localhost/<path> is similar to how other schemes treat missing
 
2125
       * hostnames.  See RFC 1808. */
 
2126
 
 
2127
      /* This cannot be done with strcpy() in a portable manner, since the
 
2128
         memory areas overlap! */
 
2129
      memmove(conn->path, conn->path + 2, strlen(conn->path + 2)+1);
 
2130
    }
1350
2131
    /*
1351
2132
     * we deal with file://<host>/<path> differently since it supports no
1352
2133
     * hostname other than "localhost" and "127.0.0.1", which is unique among
1358
2139
      char *ptr=strchr(conn->path, '/');
1359
2140
      if(ptr) {
1360
2141
        /* there was a slash present
1361
 
           
 
2142
 
1362
2143
           RFC1738 (section 3.1, page 5) says:
1363
 
 
 
2144
 
1364
2145
           The rest of the locator consists of data specific to the scheme,
1365
2146
           and is known as the "url-path". It supplies the details of how the
1366
2147
           specified resource can be accessed. Note that the "/" between the
1367
2148
           host (or port) and the url-path is NOT part of the url-path.
1368
 
 
 
2149
 
1369
2150
           As most agents use file://localhost/foo to get '/foo' although the
1370
2151
           slash preceeding foo is a separator and not a slash for the path,
1371
2152
           a URL as file://localhost//foo must be valid as well, to refer to
1375
2156
        if(ptr[1] && ('/' == ptr[1]))
1376
2157
          /* if there was two slashes, we skip the first one as that is then
1377
2158
             used truly as a separator */
1378
 
          ptr++; 
1379
 
        
1380
 
        strcpy(conn->path, ptr);
 
2159
          ptr++;
 
2160
 
 
2161
        /* This cannot be made with strcpy, as the memory chunks overlap! */
 
2162
        memmove(conn->path, ptr, strlen(ptr)+1);
1381
2163
      }
1382
2164
    }
1383
2165
 
1385
2167
  }
1386
2168
  else {
1387
2169
    /* Set default host and default path */
1388
 
    strcpy(conn->gname, "curl.haxx.se");
 
2170
    strcpy(conn->namebuffer, "curl.haxx.se");
1389
2171
    strcpy(conn->path, "/");
1390
 
 
 
2172
    /* We need to search for '/' OR '?' - whichever comes first after host
 
2173
     * name but before the path. We need to change that to handle things like
 
2174
     * http://example.com?param= (notice the missing '/'). Later we'll insert
 
2175
     * that missing slash at the beginning of the path.
 
2176
     */
1391
2177
    if (2 > sscanf(data->change.url,
1392
 
                   "%64[^\n:]://%512[^\n/]%[^\n]",
1393
 
                   conn->protostr, conn->gname, conn->path)) {
1394
 
      
 
2178
                   "%64[^\n:]://%[^\n/?]%[^\n]",
 
2179
                   conn->protostr,
 
2180
                   conn->namebuffer, conn->path)) {
 
2181
 
1395
2182
      /*
1396
2183
       * The URL was badly formatted, let's try the browser-style _without_
1397
2184
       * protocol specified like 'http://'.
1398
2185
       */
1399
 
      if((1 > sscanf(data->change.url, "%512[^\n/]%[^\n]",
1400
 
                     conn->gname, conn->path)) ) {
 
2186
      if((1 > sscanf(data->change.url, "%[^\n/?]%[^\n]",
 
2187
                     conn->namebuffer, conn->path)) ) {
1401
2188
        /*
1402
2189
         * We couldn't even get this format.
1403
2190
         */
1410
2197
       * is based on the first letters of the server name.
1411
2198
       */
1412
2199
 
1413
 
      if(strnequal(conn->gname, "FTP", 3)) {
1414
 
        strcpy(conn->protostr, "ftp");
1415
 
      }
1416
 
      else if(strnequal(conn->gname, "GOPHER", 6))
 
2200
      /* Note: if you add a new protocol, please update the list in
 
2201
       * lib/version.c too! */
 
2202
 
 
2203
      if(checkprefix("GOPHER", conn->namebuffer))
1417
2204
        strcpy(conn->protostr, "gopher");
1418
2205
#ifdef USE_SSLEAY
1419
 
      else if(strnequal(conn->gname, "HTTPS", 5))
 
2206
      else if(checkprefix("HTTPS", conn->namebuffer))
1420
2207
        strcpy(conn->protostr, "https");
1421
 
      else if(strnequal(conn->gname, "FTPS", 4))
 
2208
      else if(checkprefix("FTPS", conn->namebuffer))
1422
2209
        strcpy(conn->protostr, "ftps");
1423
2210
#endif /* USE_SSLEAY */
1424
 
      else if(strnequal(conn->gname, "TELNET", 6))
 
2211
      else if(checkprefix("FTP", conn->namebuffer))
 
2212
        strcpy(conn->protostr, "ftp");
 
2213
      else if(checkprefix("TELNET", conn->namebuffer))
1425
2214
        strcpy(conn->protostr, "telnet");
1426
 
      else if (strnequal(conn->gname, "DICT", sizeof("DICT")-1))
 
2215
      else if (checkprefix("DICT", conn->namebuffer))
1427
2216
        strcpy(conn->protostr, "DICT");
1428
 
      else if (strnequal(conn->gname, "LDAP", sizeof("LDAP")-1))
 
2217
      else if (checkprefix("LDAP", conn->namebuffer))
1429
2218
        strcpy(conn->protostr, "LDAP");
1430
2219
      else {
1431
2220
        strcpy(conn->protostr, "http");
1435
2224
    }
1436
2225
  }
1437
2226
 
1438
 
  buf = data->state.buffer; /* this is our buffer */
1439
 
 
1440
 
  /*************************************************************
1441
 
   * Take care of user and password authentication stuff
1442
 
   *************************************************************/
1443
 
 
1444
 
  if(conn->bits.user_passwd && !data->set.use_netrc) {
1445
 
    data->state.user[0] =0;
1446
 
    data->state.passwd[0]=0;
1447
 
 
1448
 
    if(*data->set.userpwd != ':') {
1449
 
      /* the name is given, get user+password */
1450
 
      sscanf(data->set.userpwd, "%127[^:]:%127[^\n]",
1451
 
             data->state.user, data->state.passwd);
1452
 
    }
1453
 
    else
1454
 
      /* no name given, get the password only */
1455
 
      sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd);
1456
 
 
1457
 
    /* check for password, if no ask for one */
1458
 
    if( !data->state.passwd[0] ) {
1459
 
      if(!data->set.fpasswd ||
1460
 
         data->set.fpasswd(data->set.passwd_client,
1461
 
                       "password:", data->state.passwd,
1462
 
                           sizeof(data->state.passwd)))
1463
 
        return CURLE_BAD_PASSWORD_ENTERED;
1464
 
    }
 
2227
  /* If the URL is malformatted (missing a '/' after hostname before path) we
 
2228
   * insert a slash here. The only letter except '/' we accept to start a path
 
2229
   * is '?'.
 
2230
   */
 
2231
  if(conn->path[0] == '?') {
 
2232
    /* We need this function to deal with overlapping memory areas. We know
 
2233
       that the memory area 'path' points to is 'urllen' bytes big and that
 
2234
       is bigger than the path. Use +1 to move the zero byte too. */
 
2235
    memmove(&conn->path[1], conn->path, strlen(conn->path)+1);
 
2236
    conn->path[0] = '/';
1465
2237
  }
1466
2238
 
 
2239
  /*
 
2240
   * So if the URL was A://B/C,
 
2241
   *   conn->protostr is A
 
2242
   *   conn->namebuffer is B
 
2243
   *   conn->path is /C
 
2244
   */
 
2245
 
1467
2246
  /*************************************************************
1468
2247
   * Take care of proxy authentication stuff
1469
2248
   *************************************************************/
1470
2249
  if(conn->bits.proxy_user_passwd) {
1471
 
    data->state.proxyuser[0] =0;
1472
 
    data->state.proxypasswd[0]=0;
1473
 
 
1474
 
    if(*data->set.proxyuserpwd != ':') {
1475
 
      /* the name is given, get user+password */
1476
 
      sscanf(data->set.proxyuserpwd, "%127[^:]:%127[^\n]",
1477
 
             data->state.proxyuser, data->state.proxypasswd);
1478
 
      }
1479
 
    else
1480
 
      /* no name given, get the password only */
1481
 
      sscanf(data->set.proxyuserpwd+1, "%127[^\n]", data->state.proxypasswd);
1482
 
 
1483
 
    /* check for password, if no ask for one */
1484
 
    if( !data->state.proxypasswd[0] ) {
1485
 
      if(!data->set.fpasswd ||
1486
 
         data->set.fpasswd( data->set.passwd_client,
1487
 
                        "proxy password:",
1488
 
                        data->state.proxypasswd,
1489
 
                        sizeof(data->state.proxypasswd)))
1490
 
        return CURLE_BAD_PASSWORD_ENTERED;
1491
 
    }
1492
 
 
 
2250
    char proxyuser[MAX_CURL_USER_LENGTH]="";
 
2251
    char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
 
2252
 
 
2253
    sscanf(data->set.proxyuserpwd,
 
2254
           "%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
 
2255
           "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
 
2256
           proxyuser, proxypasswd);
 
2257
 
 
2258
    conn->proxyuser = strdup(proxyuser);
 
2259
    if(!conn->proxyuser)
 
2260
      return CURLE_OUT_OF_MEMORY;
 
2261
    
 
2262
    conn->proxypasswd = strdup(proxypasswd);
 
2263
    if(!conn->proxypasswd)
 
2264
      return CURLE_OUT_OF_MEMORY;
1493
2265
  }
1494
2266
 
1495
2267
  /*************************************************************
1496
 
   * Set a few convenience pointers 
1497
 
   *************************************************************/
1498
 
  conn->name = conn->gname;
1499
 
  conn->ppath = conn->path;
1500
 
  conn->hostname = conn->name;
1501
 
 
1502
 
 
1503
 
  /*************************************************************
1504
2268
   * Detect what (if any) proxy to use
1505
2269
   *************************************************************/
1506
2270
  if(!data->change.proxy) {
1537
2301
 
1538
2302
      nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL;
1539
2303
      while(nope) {
1540
 
        if(strlen(nope) <= strlen(conn->name)) {
 
2304
        unsigned int namelen;
 
2305
        char *endptr = strchr(conn->hostname, ':');
 
2306
        if(endptr)
 
2307
          namelen=endptr-conn->hostname;
 
2308
        else
 
2309
          namelen=strlen(conn->hostname);
 
2310
 
 
2311
        if(strlen(nope) <= namelen) {
1541
2312
          char *checkn=
1542
 
            conn->name + strlen(conn->name) - strlen(nope);
1543
 
          if(strnequal(nope, checkn, strlen(nope))) {
 
2313
            conn->hostname + namelen - strlen(nope);
 
2314
          if(checkprefix(nope, checkn)) {
1544
2315
            /* no proxy for this host! */
1545
2316
            break;
1546
2317
          }
1555
2326
 
1556
2327
        /* Now, build <protocol>_proxy and check for such a one to use */
1557
2328
        while(*protop)
1558
 
          *envp++ = tolower(*protop++);
 
2329
          *envp++ = tolower((int)*protop++);
1559
2330
 
1560
2331
        /* append _proxy */
1561
2332
        strcpy(envp, "_proxy");
1571
2342
         * environment (cgi or php), this environment variable can
1572
2343
         * be controlled by the web server user by setting the
1573
2344
         * http header 'Proxy:' to some value.
1574
 
         * 
 
2345
         *
1575
2346
         * This can cause 'internal' http/ftp requests to be
1576
2347
         * arbitrarily redirected by any external attacker.
1577
2348
         */
1578
2349
        if(!prox && !strequal("http_proxy", proxy_env)) {
1579
2350
          /* There was no lowercase variable, try the uppercase version: */
1580
2351
          for(envp = proxy_env; *envp; envp++)
1581
 
            *envp = toupper(*envp);
 
2352
            *envp = toupper((int)*envp);
1582
2353
          prox=curl_getenv(proxy_env);
1583
2354
        }
1584
2355
 
1593
2364
 
1594
2365
        if(proxy && *proxy) {
1595
2366
          /* we have a proxy here to set */
 
2367
          char *ptr;
 
2368
          char proxyuser[MAX_CURL_USER_LENGTH];
 
2369
          char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
 
2370
 
 
2371
          char *fineptr;
 
2372
 
 
2373
          /* skip the possible protocol piece */
 
2374
          ptr=strstr(proxy, "://");
 
2375
          if(ptr)
 
2376
            ptr += 3;
 
2377
          else
 
2378
            ptr = proxy;
 
2379
 
 
2380
          fineptr = ptr;
 
2381
 
 
2382
          /* check for an @-letter */
 
2383
          ptr = strchr(ptr, '@');
 
2384
          if(ptr && (2 == sscanf(fineptr,
 
2385
                                 "%" MAX_CURL_USER_LENGTH_TXT"[^:]:"
 
2386
                                 "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
 
2387
                                 proxyuser, proxypasswd))) {
 
2388
            /* found user and password, rip them out */
 
2389
            Curl_safefree(conn->proxyuser);
 
2390
            conn->proxyuser = strdup(proxyuser);
 
2391
 
 
2392
            if(!conn->proxyuser)
 
2393
              return CURLE_OUT_OF_MEMORY;
 
2394
            
 
2395
            Curl_safefree(conn->proxypasswd);
 
2396
            conn->proxypasswd = strdup(proxypasswd);
 
2397
 
 
2398
            if(!conn->proxypasswd)
 
2399
              return CURLE_OUT_OF_MEMORY;
 
2400
            
 
2401
            conn->bits.proxy_user_passwd = TRUE; /* enable it */
 
2402
 
 
2403
            ptr = strdup(ptr+1); /* the right side of the @-letter */
 
2404
            free(proxy); /* free the former data */
 
2405
            proxy = ptr; /* now use this instead */
 
2406
          }
 
2407
 
 
2408
 
1596
2409
          data->change.proxy = proxy;
1597
2410
          data->change.proxy_alloc=TRUE; /* this needs to be freed later */
1598
2411
          conn->bits.httpproxy = TRUE;
1622
2435
    conn->protocol &= ~PROT_MISSING; /* switch that one off again */
1623
2436
  }
1624
2437
 
 
2438
#ifndef CURL_DISABLE_HTTP
1625
2439
  /************************************************************
1626
2440
   * RESUME on a HTTP page is a tricky business. First, let's just check that
1627
2441
   * 'range' isn't used, then set the range parameter and leave the resume as
1634
2448
  if(conn->resume_from) {
1635
2449
    if(!conn->bits.use_range) {
1636
2450
      /* if it already was in use, we just skip this */
1637
 
      snprintf(resumerange, sizeof(resumerange), "%d-", conn->resume_from);
 
2451
      snprintf(resumerange, sizeof(resumerange), "%" FORMAT_OFF_T "-",
 
2452
               conn->resume_from);
1638
2453
      conn->range=strdup(resumerange); /* tell ourselves to fetch this range */
1639
2454
      conn->bits.rangestringalloc = TRUE; /* mark as allocated */
1640
2455
      conn->bits.use_range = 1; /* switch on range usage */
1641
2456
    }
1642
2457
  }
1643
 
 
 
2458
#endif
1644
2459
  /*************************************************************
1645
2460
   * Setup internals depending on protocol
1646
2461
   *************************************************************/
1647
2462
 
1648
2463
  if (strequal(conn->protostr, "HTTP")) {
 
2464
#ifndef CURL_DISABLE_HTTP
1649
2465
    conn->port = (data->set.use_port && data->state.allow_port)?
1650
2466
      data->set.use_port:PORT_HTTP;
1651
2467
    conn->remote_port = PORT_HTTP;
1652
2468
    conn->protocol |= PROT_HTTP;
1653
2469
    conn->curl_do = Curl_http;
 
2470
    conn->curl_do_more = NULL;
1654
2471
    conn->curl_done = Curl_http_done;
1655
2472
    conn->curl_connect = Curl_http_connect;
 
2473
#else
 
2474
    failf(data, LIBCURL_NAME
 
2475
          " was built with HTTP disabled, http: not supported!");
 
2476
    return CURLE_UNSUPPORTED_PROTOCOL;
 
2477
#endif
1656
2478
  }
1657
2479
  else if (strequal(conn->protostr, "HTTPS")) {
1658
 
#ifdef USE_SSLEAY
 
2480
#if defined(USE_SSLEAY) && !defined(CURL_DISABLE_HTTP)
1659
2481
 
1660
2482
    conn->port = (data->set.use_port && data->state.allow_port)?
1661
2483
      data->set.use_port:PORT_HTTPS;
1663
2485
    conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL;
1664
2486
 
1665
2487
    conn->curl_do = Curl_http;
 
2488
    conn->curl_do_more = NULL;
1666
2489
    conn->curl_done = Curl_http_done;
1667
2490
    conn->curl_connect = Curl_http_connect;
1668
2491
 
1673
2496
#endif /* !USE_SSLEAY */
1674
2497
  }
1675
2498
  else if (strequal(conn->protostr, "GOPHER")) {
 
2499
#ifndef CURL_DISABLE_GOPHER
1676
2500
    conn->port = (data->set.use_port && data->state.allow_port)?
1677
2501
      data->set.use_port:PORT_GOPHER;
1678
2502
    conn->remote_port = PORT_GOPHER;
1679
2503
    /* Skip /<item-type>/ in path if present */
1680
2504
    if (isdigit((int)conn->path[1])) {
1681
 
      conn->ppath = strchr(&conn->path[1], '/');
1682
 
      if (conn->ppath == NULL)
1683
 
        conn->ppath = conn->path;
1684
 
      }
 
2505
      conn->path = strchr(&conn->path[1], '/');
 
2506
      if (conn->path == NULL)
 
2507
        conn->path = conn->pathbuffer;
 
2508
    }
1685
2509
    conn->protocol |= PROT_GOPHER;
1686
2510
    conn->curl_do = Curl_http;
 
2511
    conn->curl_do_more = NULL;
1687
2512
    conn->curl_done = Curl_http_done;
 
2513
#else
 
2514
    failf(data, LIBCURL_NAME
 
2515
          " was built with GOPHER disabled, gopher: not supported!");
 
2516
#endif
1688
2517
  }
1689
2518
  else if(strequal(conn->protostr, "FTP") ||
1690
2519
          strequal(conn->protostr, "FTPS")) {
 
2520
 
 
2521
/* MN 06/07/02 */
 
2522
#ifndef CURL_DISABLE_FTP
1691
2523
    char *type;
 
2524
    int port = PORT_FTP;
1692
2525
 
1693
2526
    if(strequal(conn->protostr, "FTPS")) {
1694
2527
#ifdef USE_SSLEAY
1695
2528
      conn->protocol |= PROT_FTPS|PROT_SSL;
 
2529
      conn->ssl[SECONDARYSOCKET].use = TRUE; /* send data securely */
 
2530
      port = PORT_FTPS;
1696
2531
#else
1697
2532
      failf(data, LIBCURL_NAME
1698
2533
            " was built with SSL disabled, ftps: not supported!");
1701
2536
    }
1702
2537
 
1703
2538
    conn->port = (data->set.use_port && data->state.allow_port)?
1704
 
      data->set.use_port:PORT_FTP;
1705
 
    conn->remote_port = PORT_FTP;
 
2539
      data->set.use_port:port;
 
2540
    conn->remote_port = port;
1706
2541
    conn->protocol |= PROT_FTP;
1707
2542
 
1708
2543
    if(data->change.proxy &&
 
2544
       *data->change.proxy &&
1709
2545
       !data->set.tunnel_thru_httpproxy) {
1710
2546
      /* Unless we have asked to tunnel ftp operations through the proxy, we
1711
2547
         switch and use HTTP operations only */
1715
2551
        failf(data, "ftps does not work through http proxy!");
1716
2552
        return CURLE_UNSUPPORTED_PROTOCOL;
1717
2553
      }
 
2554
#ifndef CURL_DISABLE_HTTP
1718
2555
      conn->curl_do = Curl_http;
1719
2556
      conn->curl_done = Curl_http_done;
 
2557
#else
 
2558
      failf(data, "FTP over http proxy requires HTTP support built-in!");
 
2559
      return CURLE_UNSUPPORTED_PROTOCOL;
 
2560
#endif
1720
2561
    }
1721
2562
    else {
1722
2563
      conn->curl_do = Curl_ftp;
 
2564
      conn->curl_do_more = Curl_ftp_nextconnect;
1723
2565
      conn->curl_done = Curl_ftp_done;
1724
2566
      conn->curl_connect = Curl_ftp_connect;
1725
2567
      conn->curl_disconnect = Curl_ftp_disconnect;
1726
2568
    }
1727
2569
 
1728
 
    conn->ppath++; /* don't include the initial slash */
 
2570
    conn->path++; /* don't include the initial slash */
1729
2571
 
1730
2572
    /* FTP URLs support an extension like ";type=<typecode>" that
1731
2573
     * we'll try to get now! */
1732
 
    type=strstr(conn->ppath, ";type=");
 
2574
    type=strstr(conn->path, ";type=");
1733
2575
    if(!type) {
1734
 
      type=strstr(conn->gname, ";type=");
 
2576
      type=strstr(conn->namebuffer, ";type=");
1735
2577
    }
1736
2578
    if(type) {
1737
2579
      char command;
1738
 
      *type=0;
1739
 
      command = toupper(type[6]);
 
2580
      *type=0;                     /* it was in the middle of the hostname */
 
2581
      command = toupper((int)type[6]);
1740
2582
      switch(command) {
1741
2583
      case 'A': /* ASCII mode */
1742
2584
        data->set.ftp_ascii = 1;
1751
2593
        break;
1752
2594
      }
1753
2595
    }
 
2596
 
 
2597
/* MN 06/07/02 */
 
2598
#else /* CURL_DISABLE_FTP */
 
2599
    failf(data, LIBCURL_NAME
 
2600
          " was built with FTP disabled, ftp/ftps: not supported!");
 
2601
    return CURLE_UNSUPPORTED_PROTOCOL;
 
2602
#endif
1754
2603
  }
1755
2604
  else if(strequal(conn->protostr, "TELNET")) {
 
2605
#ifndef CURL_DISABLE_TELNET
1756
2606
    /* telnet testing factory */
1757
2607
    conn->protocol |= PROT_TELNET;
1758
2608
 
1761
2611
    conn->remote_port = PORT_TELNET;
1762
2612
    conn->curl_do = Curl_telnet;
1763
2613
    conn->curl_done = Curl_telnet_done;
 
2614
#else
 
2615
    failf(data, LIBCURL_NAME
 
2616
          " was built with TELNET disabled!");
 
2617
#endif
1764
2618
  }
1765
2619
  else if (strequal(conn->protostr, "DICT")) {
 
2620
#ifndef CURL_DISABLE_DICT
1766
2621
    conn->protocol |= PROT_DICT;
1767
2622
    conn->port = (data->set.use_port && data->state.allow_port)?
1768
2623
      data->set.use_port:PORT_DICT;
1769
2624
    conn->remote_port = PORT_DICT;
1770
2625
    conn->curl_do = Curl_dict;
1771
2626
    conn->curl_done = NULL; /* no DICT-specific done */
 
2627
#else
 
2628
    failf(data, LIBCURL_NAME
 
2629
          " was built with DICT disabled!");
 
2630
#endif
1772
2631
  }
1773
2632
  else if (strequal(conn->protostr, "LDAP")) {
 
2633
#ifndef CURL_DISABLE_LDAP
1774
2634
    conn->protocol |= PROT_LDAP;
1775
2635
    conn->port = (data->set.use_port && data->state.allow_port)?
1776
2636
      data->set.use_port:PORT_LDAP;
1777
2637
    conn->remote_port = PORT_LDAP;
1778
2638
    conn->curl_do = Curl_ldap;
1779
2639
    conn->curl_done = NULL; /* no LDAP-specific done */
 
2640
#else
 
2641
    failf(data, LIBCURL_NAME
 
2642
          " was built with LDAP disabled!");
 
2643
#endif
1780
2644
  }
1781
2645
  else if (strequal(conn->protostr, "FILE")) {
 
2646
#ifndef CURL_DISABLE_FILE
1782
2647
    conn->protocol |= PROT_FILE;
1783
2648
 
1784
2649
    conn->curl_do = Curl_file;
1790
2655
 
1791
2656
    /* Setup a "faked" transfer that'll do nothing */
1792
2657
    if(CURLE_OK == result) {
 
2658
      conn->bits.tcpconnect = TRUE; /* we are "connected */
1793
2659
      result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
1794
2660
                             -1, NULL); /* no upload */
1795
2661
    }
1796
2662
 
1797
2663
    return result;
 
2664
#else
 
2665
    failf(data, LIBCURL_NAME
 
2666
          " was built with FILE disabled!");
 
2667
#endif
1798
2668
  }
1799
2669
  else {
1800
2670
    /* We fell through all checks and thus we don't support the specified
1804
2674
  }
1805
2675
 
1806
2676
  /*************************************************************
1807
 
   * .netrc scanning coming up
1808
 
   *************************************************************/
1809
 
  if(data->set.use_netrc) {
1810
 
    if(Curl_parsenetrc(conn->hostname,
1811
 
                       data->state.user,
1812
 
                       data->state.passwd)) {
1813
 
      infof(data, "Couldn't find host %s in the .netrc file, using defaults",
1814
 
            conn->hostname);
1815
 
    }
1816
 
    else
1817
 
      conn->bits.user_passwd = 1; /* enable user+password */
1818
 
 
1819
 
    /* weather we failed or not, we don't know which fields that were filled
1820
 
       in anyway */
1821
 
    if(!data->state.user[0])
1822
 
      strcpy(data->state.user, CURL_DEFAULT_USER);
1823
 
    if(!data->state.passwd[0])
1824
 
      strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
1825
 
  }
1826
 
  else if(!(conn->bits.user_passwd) &&
1827
 
          (conn->protocol & (PROT_FTP|PROT_HTTP)) ) {
1828
 
    /* This is a FTP or HTTP URL, and we haven't got the user+password in
1829
 
     * the extra parameter, we will now try to extract the possible
1830
 
     * user+password pair in a string like:
1831
 
     * ftp://user:password@ftp.my.site:8021/README */
1832
 
    char *ptr=NULL; /* assign to remove possible warnings */
1833
 
    if((ptr=strchr(conn->name, '@'))) {
1834
 
      /* there's a user+password given here, to the left of the @ */
1835
 
 
1836
 
      data->state.user[0] =0;
1837
 
      data->state.passwd[0]=0;
1838
 
 
1839
 
      if(*conn->name != ':') {
1840
 
        /* the name is given, get user+password */
1841
 
        sscanf(conn->name, "%127[^:@]:%127[^@]",
1842
 
               data->state.user, data->state.passwd);
1843
 
      }
1844
 
      else
1845
 
        /* no name given, get the password only */
1846
 
        sscanf(conn->name+1, "%127[^@]", data->state.passwd);
1847
 
 
1848
 
      if(data->state.user[0]) {
1849
 
        char *newname=curl_unescape(data->state.user, 0);
1850
 
        if(strlen(newname) < sizeof(data->state.user)) {
1851
 
          strcpy(data->state.user, newname);
1852
 
        }
1853
 
        /* if the new name is longer than accepted, then just use
1854
 
           the unconverted name, it'll be wrong but what the heck */
1855
 
        free(newname);
1856
 
      }
1857
 
 
1858
 
      /* check for password, if no ask for one */
1859
 
      if( !data->state.passwd[0] ) {
1860
 
        if(!data->set.fpasswd ||
1861
 
           data->set.fpasswd(data->set.passwd_client,
1862
 
                             "password:", data->state.passwd,
1863
 
                             sizeof(data->state.passwd)))
1864
 
          return CURLE_BAD_PASSWORD_ENTERED;
1865
 
      }
1866
 
      else {
1867
 
        /* we have a password found in the URL, decode it! */
1868
 
        char *newpasswd=curl_unescape(data->state.passwd, 0);
1869
 
        if(strlen(newpasswd) < sizeof(data->state.passwd)) {
1870
 
          strcpy(data->state.passwd, newpasswd);
1871
 
        }
1872
 
        free(newpasswd);
1873
 
      }
1874
 
 
1875
 
      conn->name = ++ptr;
1876
 
      conn->bits.user_passwd=TRUE; /* enable user+password */
1877
 
    }
1878
 
    else {
1879
 
      strcpy(data->state.user, CURL_DEFAULT_USER);
1880
 
      strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
1881
 
    }
1882
 
  }
1883
 
 
1884
 
  /*************************************************************
1885
2677
   * Figure out the remote port number
1886
2678
   *
1887
2679
   * No matter if we use a proxy or not, we have to figure out the remote
1889
2681
   *
1890
2682
   * To be able to detect port number flawlessly, we must not confuse them
1891
2683
   * IPv6-specified addresses in the [0::1] style. (RFC2732)
 
2684
   *
 
2685
   * The conn->hostname is currently [user:passwd@]host[:port] where host
 
2686
   * could be a hostname, IPv4 address or IPv6 address.
1892
2687
   *************************************************************/
1893
 
 
1894
 
  if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
 
2688
  if((1 == sscanf(conn->hostname, "[%*39[0-9a-fA-F:.]%c", &endbracket)) &&
1895
2689
     (']' == endbracket)) {
1896
 
    /* This is a (IPv6-style) specified IP-address. We support _any_
1897
 
       IP within brackets to be really generic. */
1898
 
    conn->name++; /* pass the starting bracket */
 
2690
    /* this is a RFC2732-style specified IP-address */
 
2691
    conn->bits.ipv6_ip = TRUE;
1899
2692
 
1900
 
    tmp = strchr(conn->name, ']');
 
2693
    conn->hostname++; /* pass the starting bracket */
 
2694
    tmp = strchr(conn->hostname, ']');
1901
2695
    *tmp = 0; /* zero terminate */
1902
 
 
1903
2696
    tmp++; /* pass the ending bracket */
1904
2697
    if(':' != *tmp)
1905
2698
      tmp = NULL; /* no port number available */
1906
2699
  }
1907
 
  else {
1908
 
    /* traditional IPv4-style port-extracting */
1909
 
    tmp = strchr(conn->name, ':');
1910
 
  }
 
2700
  else
 
2701
    tmp = strrchr(conn->hostname, ':');
1911
2702
 
1912
2703
  if (tmp) {
1913
 
    *tmp++ = '\0'; /* cut off the name there */
1914
 
    conn->remote_port = atoi(tmp);
 
2704
    char *rest;
 
2705
    unsigned long port;
 
2706
 
 
2707
    port=strtoul(tmp+1, &rest, 10);  /* Port number must be decimal */
 
2708
 
 
2709
    if (rest != (tmp+1) && *rest == '\0') {
 
2710
      /* The colon really did have only digits after it,
 
2711
       * so it is either a port number or a mistake */
 
2712
 
 
2713
      if (port > 0xffff) {   /* Single unix standard says port numbers are
 
2714
                              * 16 bits long */
 
2715
        failf(data, "Port number too large: %lu", port);
 
2716
        return CURLE_URL_MALFORMAT;
 
2717
      }
 
2718
 
 
2719
      *tmp = '\0'; /* cut off the name there */
 
2720
      conn->remote_port = (unsigned short)port;
 
2721
    }
1915
2722
  }
1916
2723
 
1917
 
  if(data->change.proxy) {
 
2724
  if(data->change.proxy && *data->change.proxy) {
1918
2725
    /* If this is supposed to use a proxy, we need to figure out the proxy
1919
2726
       host name name, so that we can re-use an existing connection
1920
2727
       that may exist registered to the same proxy host. */
1966
2773
  }
1967
2774
 
1968
2775
  /*************************************************************
 
2776
   * Take care of user and password authentication stuff
 
2777
   *************************************************************/
 
2778
 
 
2779
  /*
 
2780
   * Inputs: data->set.userpwd   (CURLOPT_USERPWD)
 
2781
   *         data->set.fpasswd   (CURLOPT_PASSWDFUNCTION)
 
2782
   *         data->set.use_netrc (CURLOPT_NETRC)
 
2783
   *         conn->hostname
 
2784
   *         netrc file
 
2785
   *         hard-coded defaults
 
2786
   *
 
2787
   * Outputs: (almost :- all currently undefined)
 
2788
   *          conn->bits.user_passwd  - non-zero if non-default passwords exist
 
2789
   *          conn->user              - non-zero length if defined
 
2790
   *          conn->passwd            -   ditto
 
2791
   *          conn->hostname          - remove user name and password
 
2792
   */
 
2793
 
 
2794
  /* At this point, we're hoping all the other special cases have
 
2795
   * been taken care of, so conn->hostname is at most
 
2796
   *    [user[:password]]@]hostname
 
2797
   *
 
2798
   * We need somewhere to put the embedded details, so do that first.
 
2799
   */
 
2800
 
 
2801
  user[0] =0;   /* to make everything well-defined */
 
2802
  passwd[0]=0;
 
2803
 
 
2804
  if (conn->protocol & (PROT_FTP|PROT_HTTP)) {
 
2805
    /* This is a FTP or HTTP URL, we will now try to extract the possible
 
2806
     * user+password pair in a string like:
 
2807
     * ftp://user:password@ftp.my.site:8021/README */
 
2808
    char *ptr=strchr(conn->hostname, '@');
 
2809
    char *userpass = conn->hostname;
 
2810
    if(ptr != NULL) {
 
2811
      /* there's a user+password given here, to the left of the @ */
 
2812
 
 
2813
      conn->hostname = ++ptr;
 
2814
 
 
2815
      /* So the hostname is sane.  Only bother interpreting the
 
2816
       * results if we could care.  It could still be wasted
 
2817
       * work because it might be overtaken by the programmatically
 
2818
       * set user/passwd, but doing that first adds more cases here :-(
 
2819
       */
 
2820
 
 
2821
      if (data->set.use_netrc != CURL_NETRC_REQUIRED) {
 
2822
        /* We could use the one in the URL */
 
2823
 
 
2824
        conn->bits.user_passwd = 1; /* enable user+password */
 
2825
 
 
2826
        if(*userpass != ':') {
 
2827
          /* the name is given, get user+password */
 
2828
          sscanf(userpass, "%127[^:@]:%127[^@]",
 
2829
                 user, passwd);
 
2830
        }
 
2831
        else
 
2832
          /* no name given, get the password only */
 
2833
          sscanf(userpass, ":%127[^@]", passwd);
 
2834
 
 
2835
        if(user[0]) {
 
2836
          char *newname=curl_unescape(user, 0);
 
2837
          if(strlen(newname) < sizeof(user)) {
 
2838
            strcpy(user, newname);
 
2839
          }
 
2840
          /* if the new name is longer than accepted, then just use
 
2841
             the unconverted name, it'll be wrong but what the heck */
 
2842
          free(newname);
 
2843
        }
 
2844
        if (passwd[0]) {
 
2845
          /* we have a password found in the URL, decode it! */
 
2846
          char *newpasswd=curl_unescape(passwd, 0);
 
2847
          if(strlen(newpasswd) < sizeof(passwd)) {
 
2848
            strcpy(passwd, newpasswd);
 
2849
          }
 
2850
          free(newpasswd);
 
2851
        }
 
2852
      }
 
2853
    }
 
2854
  }
 
2855
 
 
2856
  /* Programmatically set password:
 
2857
   *   - always applies, if available
 
2858
   *   - takes precedence over the values we just set above
 
2859
   * so scribble it over the top.
 
2860
   * User-supplied passwords are assumed not to need unescaping.
 
2861
   *
 
2862
   * user_password is set in "inherite initial knowledge' above,
 
2863
   * so it doesn't have to be set in this block
 
2864
   */
 
2865
  if (data->set.userpwd != NULL) {
 
2866
    /* the name is given, get user+password */
 
2867
    sscanf(data->set.userpwd,
 
2868
           "%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
 
2869
           "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
 
2870
           user, passwd);
 
2871
  }
 
2872
 
 
2873
  if (data->set.use_netrc != CURL_NETRC_IGNORED) {
 
2874
    if(Curl_parsenetrc(conn->hostname,
 
2875
                       user, passwd,
 
2876
                       data->set.netrc_file)) {
 
2877
      infof(data, "Couldn't find host %s in the .netrc file, using defaults\n",
 
2878
            conn->hostname);
 
2879
    }
 
2880
    else
 
2881
      conn->bits.user_passwd = 1; /* enable user+password */
 
2882
  }
 
2883
 
 
2884
  /* If our protocol needs a password and we have none, use the defaults */
 
2885
  if ( (conn->protocol & PROT_FTP) &&
 
2886
       !conn->bits.user_passwd) {
 
2887
 
 
2888
    conn->user = strdup(CURL_DEFAULT_USER);
 
2889
    conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
 
2890
 
 
2891
    /* This is the default password, so DON'T set conn->bits.user_passwd */
 
2892
  }
 
2893
  else {
 
2894
    /* store user + password, zero-length if not set */
 
2895
    conn->user = strdup(user);
 
2896
    conn->passwd = strdup(passwd);
 
2897
  }
 
2898
 
 
2899
  /*************************************************************
1969
2900
   * Check the current list of connections to see if we can
1970
2901
   * re-use an already existing one or if we have to create a
1971
2902
   * new one.
1972
2903
   *************************************************************/
1973
2904
 
1974
 
  /* reuse_fresh is set TRUE if we are told to use a fresh connection
1975
 
     by force */
1976
 
  if(!data->set.reuse_fresh &&
1977
 
     ConnectionExists(data, conn, &conn_temp)) {
 
2905
  /* get a cloned copy of the SSL config situation stored in the 
 
2906
     connection struct */
 
2907
  if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
 
2908
    return CURLE_OUT_OF_MEMORY;
 
2909
 
 
2910
  /* reuse_fresh is TRUE if we are told to use a new connection by force, but
 
2911
     we only acknowledge this option if this is not a re-used connection
 
2912
     already (which happens due to follow-location or during a HTTP
 
2913
     authentication phase). */
 
2914
  if(data->set.reuse_fresh && !data->state.this_is_a_follow)
 
2915
    reuse = FALSE;
 
2916
  else 
 
2917
    reuse = ConnectionExists(data, conn, &conn_temp);
 
2918
 
 
2919
  if(reuse) {
1978
2920
    /*
1979
2921
     * We already have a connection for this, we got the former connection
1980
2922
     * in the conn_temp variable and thus we need to cleanup the one we
1982
2924
     * existing one.
1983
2925
     */
1984
2926
    struct connectdata *old_conn = conn;
1985
 
    char *path = old_conn->path; /* setup the current path pointer properly */
1986
 
    char *ppath = old_conn->ppath; /* this is the modified path pointer */
 
2927
 
1987
2928
    if(old_conn->proxyhost)
1988
2929
      free(old_conn->proxyhost);
 
2930
 
 
2931
    /* free the SSL config struct from this connection struct as this was
 
2932
       allocated in vain and is targeted for destruction */
 
2933
    Curl_free_ssl_config(&conn->ssl_config);
 
2934
 
1989
2935
    conn = conn_temp;        /* use this connection from now on */
1990
2936
 
1991
 
    /* we need these pointers if we speak over a proxy */
1992
 
    conn->hostname = conn->gname;
1993
 
    conn->name = &conn->gname[old_conn->name - old_conn->gname];
1994
 
 
1995
 
    free(conn->path);    /* free the previously allocated path pointer */
1996
 
 
1997
 
    /* 'path' points to the allocated data, 'ppath' may have been advanced
1998
 
       to point somewhere within the 'path' area. */
1999
 
    conn->path = path; 
2000
 
    conn->ppath = ppath;
 
2937
    /* get the user+password information from the old_conn struct since it may
 
2938
     * be new for this request even when we re-use an existing connection */
 
2939
    conn->bits.user_passwd = old_conn->bits.user_passwd;
 
2940
    conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
 
2941
 
 
2942
    /* get the newly set value, not the old one */
 
2943
    conn->bits.no_body = old_conn->bits.no_body;
 
2944
 
 
2945
    free(conn->namebuffer); /* free the newly allocated name buffer */
 
2946
    conn->namebuffer = old_conn->namebuffer; /* use the old one */
 
2947
    conn->hostname = old_conn->hostname;
 
2948
 
 
2949
    free(conn->pathbuffer); /* free the newly allocated path pointer */
 
2950
    conn->pathbuffer = old_conn->pathbuffer; /* use the old one */
 
2951
    conn->path = old_conn->path;
2001
2952
 
2002
2953
    /* re-use init */
2003
2954
    conn->bits.reuse = TRUE; /* yes, we're re-using here */
2005
2956
                                 otherwise */
2006
2957
    conn->maxdownload = -1;  /* might have been used previously! */
2007
2958
 
 
2959
    Curl_safefree(old_conn->user);
 
2960
    Curl_safefree(old_conn->passwd);
 
2961
    Curl_safefree(old_conn->proxyuser);
 
2962
    Curl_safefree(old_conn->proxypasswd);
 
2963
 
 
2964
    if(old_conn->bits.rangestringalloc)
 
2965
      free(old_conn->range);
 
2966
 
2008
2967
    free(old_conn);          /* we don't need this anymore */
2009
2968
 
2010
2969
    /*
2013
2972
     */
2014
2973
    conn->resume_from = data->set.set_resume_from;
2015
2974
    if (conn->resume_from) {
2016
 
        snprintf(resumerange, sizeof(resumerange), "%d-", conn->resume_from);
2017
 
        if (conn->bits.rangestringalloc == TRUE) 
2018
 
            free(conn->range);
2019
 
        
2020
 
        /* tell ourselves to fetch this range */
2021
 
        conn->range = strdup(resumerange);
2022
 
        conn->bits.use_range = TRUE;        /* enable range download */
2023
 
        conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
 
2975
      snprintf(resumerange, sizeof(resumerange), "%" FORMAT_OFF_T "-",
 
2976
               conn->resume_from);
 
2977
      if (conn->bits.rangestringalloc == TRUE)
 
2978
        free(conn->range);
 
2979
 
 
2980
      /* tell ourselves to fetch this range */
 
2981
      conn->range = strdup(resumerange);
 
2982
      conn->bits.use_range = TRUE;        /* enable range download */
 
2983
      conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
2024
2984
    }
2025
2985
    else if (data->set.set_range) {
2026
2986
      /* There is a range, but is not a resume, useful for random ftp access */
2028
2988
      conn->bits.rangestringalloc = TRUE; /* mark range string allocated */
2029
2989
      conn->bits.use_range = TRUE;        /* enable range download */
2030
2990
    }
2031
 
    
 
2991
    else
 
2992
      conn->bits.use_range = FALSE; /* disable range download */
 
2993
 
2032
2994
    *in_connect = conn;      /* return this instead! */
2033
2995
 
2034
2996
    infof(data, "Re-using existing connection! (#%d)\n", conn->connectindex);
2041
3003
    ConnectionStore(data, conn);
2042
3004
  }
2043
3005
 
 
3006
  /* Continue connectdata initialization here.
 
3007
   *
 
3008
   * Inherit the proper values from the urldata struct AFTER we have arranged
 
3009
   * the persistant conncetion stuff */
 
3010
  conn->fread = data->set.fread;
 
3011
  conn->fread_in = data->set.in;
 
3012
 
 
3013
  conn->bits.upload_chunky =
 
3014
    ((conn->protocol&PROT_HTTP) &&
 
3015
     data->set.upload &&
 
3016
     (data->set.infilesize == -1) &&
 
3017
     (data->set.httpversion != CURL_HTTP_VERSION_1_0))?
 
3018
    /* HTTP, upload, unknown file size and not HTTP 1.0 */
 
3019
    TRUE:
 
3020
  /* else, no chunky upload */
 
3021
  FALSE;
 
3022
 
 
3023
#ifndef USE_ARES
2044
3024
  /*************************************************************
2045
 
   * Set timeout if that is being used
 
3025
   * Set timeout if that is being used, and we're not using an asynchronous
 
3026
   * name resolve.
2046
3027
   *************************************************************/
2047
 
  if(data->set.timeout || data->set.connecttimeout) {
 
3028
  if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) {
2048
3029
    /*************************************************************
2049
3030
     * Set signal handler to catch SIGALRM
2050
3031
     * Store the old value to be able to set it back later!
2051
3032
     *************************************************************/
2052
3033
 
 
3034
#ifdef SIGALRM
2053
3035
#ifdef HAVE_SIGACTION
2054
3036
    struct sigaction sigact;
2055
3037
    sigaction(SIGALRM, NULL, &sigact);
2062
3044
#endif
2063
3045
    /* now set the new struct */
2064
3046
    sigaction(SIGALRM, &sigact, NULL);
2065
 
#else
 
3047
#else /* HAVE_SIGACTION */
2066
3048
    /* no sigaction(), revert to the much lamer signal() */
2067
3049
#ifdef HAVE_SIGNAL
2068
3050
    keep_sigact = signal(SIGALRM, alarmfunc);
2069
3051
#endif
2070
 
#endif
 
3052
#endif /* HAVE_SIGACTION */
2071
3053
 
2072
3054
    /* We set the timeout on the name resolving phase first, separately from
2073
3055
     * the download/upload part to allow a maximum time on everything. This is
2084
3066
       recently set in the beginning of this function and nothing slow
2085
3067
       has been done since then until now. */
2086
3068
#endif
 
3069
#endif /* SIGALRM */
2087
3070
  }
2088
 
 
 
3071
#endif /* USE_ARES */
 
3072
  
2089
3073
  /*************************************************************
2090
3074
   * Resolve the name of the server or proxy
2091
3075
   *************************************************************/
2092
 
  if(!data->change.proxy) {
 
3076
  if(conn->bits.reuse) {
 
3077
    /* re-used connection, no resolving is necessary */
 
3078
    hostaddr = NULL;
 
3079
    conn->connect_addr = NULL; /* we don't connect now so we don't have any
 
3080
                                  fresh connect_addr struct to point to */
 
3081
  }
 
3082
  else if(!data->change.proxy || !*data->change.proxy) {
2093
3083
    /* If not connecting via a proxy, extract the port from the URL, if it is
2094
3084
     * there, thus overriding any defaults that might have been set above. */
2095
3085
    conn->port =  conn->remote_port; /* it is the same port */
2096
3086
 
2097
3087
    /* Resolve target host right on */
2098
 
    if(!conn->hostaddr) {
2099
 
      /* it might already be set if reusing a connection */
2100
 
      conn->hostaddr = Curl_resolv(data, conn->name, conn->port,
2101
 
                                   &conn->hostent_buf);
2102
 
    }
2103
 
    if(!conn->hostaddr) {
2104
 
      failf(data, "Couldn't resolve host '%s'", conn->name);
 
3088
    rc = Curl_resolv(conn, conn->hostname, conn->port, &hostaddr);
 
3089
    if(rc == 1)
 
3090
      *async = TRUE;
 
3091
 
 
3092
    else if(!hostaddr) {
 
3093
      failf(data, "Couldn't resolve host '%s'", conn->hostname);
2105
3094
      result =  CURLE_COULDNT_RESOLVE_HOST;
2106
3095
      /* don't return yet, we need to clean up the timeout first */
2107
3096
    }
2108
3097
  }
2109
 
  else if(!conn->hostaddr) {
2110
 
    /* This is a proxy that hasn't been resolved yet. It may be resolved
2111
 
       if we're reusing an existing connection. */
 
3098
  else {
 
3099
    /* This is a proxy that hasn't been resolved yet. */
2112
3100
 
2113
3101
    /* resolve proxy */
2114
 
    /* it might already be set if reusing a connection */
2115
 
    conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port,
2116
 
                                 &conn->hostent_buf);
2117
 
 
2118
 
    if(!conn->hostaddr) {
 
3102
    rc = Curl_resolv(conn, conn->proxyhost, conn->port, &hostaddr);
 
3103
 
 
3104
    if(rc == 1)
 
3105
      *async = TRUE;
 
3106
 
 
3107
    else if(!hostaddr) {
2119
3108
      failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
2120
3109
      result = CURLE_COULDNT_RESOLVE_PROXY;
2121
3110
      /* don't return yet, we need to clean up the timeout first */
2122
3111
    }
2123
3112
  }
2124
 
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);
2125
 
#ifdef HAVE_ALARM
2126
 
  if(data->set.timeout || data->set.connecttimeout) {
 
3113
  *addr = hostaddr;
 
3114
 
 
3115
#if defined(HAVE_ALARM) && defined(SIGALRM)
 
3116
  if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) {
2127
3117
#ifdef HAVE_SIGACTION
2128
3118
    if(keep_copysig) {
2129
3119
      /* we got a struct as it looked before, now put that one back nice
2135
3125
    /* restore the previous SIGALRM handler */
2136
3126
    signal(SIGALRM, keep_sigact);
2137
3127
#endif
2138
 
#endif
 
3128
#endif /* HAVE_SIGACTION */
 
3129
 
2139
3130
    /* switch back the alarm() to either zero or to what it was before minus
2140
3131
       the time we spent until now! */
2141
3132
    if(prev_alarm) {
2161
3152
      alarm(0); /* just shut it off */
2162
3153
  }
2163
3154
#endif
2164
 
  if(result)
 
3155
 
 
3156
  return result;
 
3157
}
 
3158
 
 
3159
/* SetupConnection() should be called after the name resolve initiated in
 
3160
 * CreateConnection() is all done.
 
3161
 */
 
3162
 
 
3163
static CURLcode SetupConnection(struct connectdata *conn,
 
3164
                                struct Curl_dns_entry *hostaddr)
 
3165
{
 
3166
  struct SessionHandle *data = conn->data;
 
3167
  CURLcode result=CURLE_OK;
 
3168
 
 
3169
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);
 
3170
 
 
3171
  if(conn->protocol & PROT_FILE)
 
3172
    /* There's nothing in this function to setup if we're only doing
 
3173
       a file:// transfer */
2165
3174
    return result;
2166
3175
 
2167
3176
  /*************************************************************
2168
 
   * Proxy authentication
2169
 
   *************************************************************/
2170
 
  if(conn->bits.proxy_user_passwd) {
2171
 
    char *authorization;
2172
 
    snprintf(data->state.buffer, BUFSIZE, "%s:%s",
2173
 
             data->state.proxyuser, data->state.proxypasswd);
2174
 
    if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer),
2175
 
                          &authorization) >= 0) {
2176
 
      if(conn->allocptr.proxyuserpwd)
2177
 
        free(conn->allocptr.proxyuserpwd);
2178
 
      conn->allocptr.proxyuserpwd =
2179
 
        aprintf("Proxy-authorization: Basic %s\015\012", authorization);
2180
 
      free(authorization);
2181
 
    }
2182
 
  }
2183
 
 
2184
 
  /*************************************************************
2185
3177
   * Send user-agent to HTTP proxies even if the target protocol
2186
3178
   * isn't HTTP.
2187
3179
   *************************************************************/
2188
 
  if((conn->protocol&PROT_HTTP) || data->change.proxy) {
 
3180
  if((conn->protocol&PROT_HTTP) ||
 
3181
     (data->change.proxy && *data->change.proxy)) {
2189
3182
    if(data->set.useragent) {
2190
 
      if(conn->allocptr.uagent)
2191
 
        free(conn->allocptr.uagent);
 
3183
      Curl_safefree(conn->allocptr.uagent);
2192
3184
      conn->allocptr.uagent =
2193
3185
        aprintf("User-Agent: %s\015\012", data->set.useragent);
2194
3186
    }
2195
3187
  }
2196
3188
 
2197
 
  if(-1 == conn->firstsocket) {
 
3189
  if(data->set.encoding) {
 
3190
    Curl_safefree(conn->allocptr.accept_encoding);
 
3191
    conn->allocptr.accept_encoding =
 
3192
      aprintf("Accept-Encoding: %s\015\012", data->set.encoding);
 
3193
  }
 
3194
 
 
3195
  conn->bytecount = 0;
 
3196
  conn->headerbytecount = 0;
 
3197
 
 
3198
  if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
 
3199
    bool connected;
 
3200
 
2198
3201
    /* Connect only if not already connected! */
2199
 
    result = ConnectPlease(conn);
 
3202
    result = ConnectPlease(conn, hostaddr, &connected);
 
3203
 
 
3204
    if(connected) {
 
3205
      result = Curl_protocol_connect(conn, hostaddr);
 
3206
      if(CURLE_OK == result)
 
3207
        conn->bits.tcpconnect = TRUE;
 
3208
    }
 
3209
    else
 
3210
      conn->bits.tcpconnect = FALSE;
 
3211
 
 
3212
 
2200
3213
    if(CURLE_OK != result)
2201
3214
      return result;
2202
 
 
2203
 
    if(conn->curl_connect) {
2204
 
      /* is there a connect() procedure? */
2205
 
 
2206
 
      /* set start time here for timeout purposes in the
2207
 
       * connect procedure, it is later set again for the
2208
 
       * progress meter purpose */
2209
 
      conn->now = Curl_tvnow();
2210
 
 
2211
 
      /* Call the protocol-specific connect function */
2212
 
      result = conn->curl_connect(conn);
2213
 
      if(result != CURLE_OK)
2214
 
        return result; /* pass back errors */
2215
 
    }
2216
 
  }
2217
 
 
2218
 
  Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected */
2219
 
 
2220
 
  conn->now = Curl_tvnow(); /* time this *after* the connect is done */
2221
 
  conn->bytecount = 0;
2222
 
  conn->headerbytecount = 0;
2223
 
  
2224
 
  /* Figure out the ip-number and display the first host name it shows: */
2225
 
#ifdef ENABLE_IPV6
2226
 
  {
2227
 
    char hbuf[NI_MAXHOST];
2228
 
#ifdef NI_WITHSCOPEID
2229
 
    const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
2230
 
#else
2231
 
    const int niflags = NI_NUMERICHOST;
2232
 
#endif
2233
 
    struct addrinfo *ai = conn->serv_addr;
2234
 
 
2235
 
    if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
2236
 
        niflags)) {
2237
 
      snprintf(hbuf, sizeof(hbuf), "?");
2238
 
    }
2239
 
    if (ai->ai_canonname) {
2240
 
      infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
2241
 
            conn->port);
2242
 
    } else {
2243
 
      infof(data, "Connected to %s port %d\n", hbuf, conn->port);
2244
 
    }
2245
 
  }
2246
 
#else
2247
 
  {
2248
 
    struct in_addr in;
2249
 
    (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
2250
 
    infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name,
2251
 
#if defined(HAVE_INET_NTOA_R)
2252
 
          inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf))
2253
 
#else
2254
 
          inet_ntoa(in)
2255
 
#endif
2256
 
          );
2257
 
  }
2258
 
#endif
 
3215
  }
 
3216
  else {
 
3217
    Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
 
3218
    conn->bits.tcpconnect = TRUE;
 
3219
    if(data->set.verbose)
 
3220
      verboseconnect(conn, hostaddr);
 
3221
  }
 
3222
 
 
3223
  conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
 
3224
                               set this here perhaps a second time */
2259
3225
 
2260
3226
#ifdef __EMX__
2261
3227
  /* 20000330 mgs
2273
3239
}
2274
3240
 
2275
3241
CURLcode Curl_connect(struct SessionHandle *data,
2276
 
                      struct connectdata **in_connect)
 
3242
                      struct connectdata **in_connect,
 
3243
                      bool *asyncp)
2277
3244
{
2278
3245
  CURLcode code;
2279
 
  struct connectdata *conn;
 
3246
  struct Curl_dns_entry *dns;
2280
3247
 
 
3248
  *asyncp = FALSE; /* assume synchronous resolves by default */
 
3249
  
2281
3250
  /* call the stuff that needs to be called */
2282
 
  code = CreateConnection(data, in_connect);
 
3251
  code = CreateConnection(data, in_connect, &dns, asyncp);
2283
3252
 
 
3253
  if(CURLE_OK == code) {
 
3254
    /* no error */
 
3255
    if(dns || !*asyncp)
 
3256
      /* If an address is available it means that we already have the name
 
3257
         resolved, OR it isn't async.
 
3258
         If so => continue connecting from here */
 
3259
      code = SetupConnection(*in_connect, dns);
 
3260
    /* else
 
3261
         response will be received and treated async wise */
 
3262
  }
 
3263
  
2284
3264
  if(CURLE_OK != code) {
2285
3265
    /* We're not allowed to return failure with memory left allocated
2286
3266
       in the connectdata struct, free those here */
2287
 
    conn = (struct connectdata *)*in_connect;
2288
 
    if(conn) {
2289
 
      Curl_disconnect(conn);      /* close the connection */
2290
 
      *in_connect = NULL;         /* return a NULL */
 
3267
    if(*in_connect) {
 
3268
      Curl_disconnect(*in_connect); /* close the connection */
 
3269
      *in_connect = NULL;           /* return a NULL */
2291
3270
    }
2292
3271
  }
2293
 
  return code;
 
3272
 
 
3273
  return code;
 
3274
}
 
3275
 
 
3276
/* Call this function after Curl_connect() has returned async=TRUE and
 
3277
   then a successful name resolve has been received */
 
3278
CURLcode Curl_async_resolved(struct connectdata *conn)
 
3279
{
 
3280
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME)
 
3281
  CURLcode code = SetupConnection(conn, conn->async.dns);
 
3282
 
 
3283
  if(code)
 
3284
    /* We're not allowed to return failure with memory left allocated
 
3285
       in the connectdata struct, free those here */
 
3286
    Curl_disconnect(conn); /* close the connection */
 
3287
 
 
3288
  return code;
 
3289
#else
 
3290
  (void)conn;
 
3291
  return CURLE_OK;
 
3292
#endif
2294
3293
}
2295
3294
 
2296
3295
 
2311
3310
    free(conn->newurl);
2312
3311
    conn->newurl = NULL;
2313
3312
  }
2314
 
 
 
3313
 
 
3314
  if(conn->connect_addr)
 
3315
    Curl_resolv_unlock(conn->data, conn->connect_addr); /* done with this */
 
3316
 
 
3317
#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
 
3318
  /* scan for DNS cache entries still marked as in use */
 
3319
  Curl_hash_apply(data->hostcache,
 
3320
                  NULL, Curl_scan_cache_used);
 
3321
#endif
 
3322
 
 
3323
  Curl_hostcache_prune(data); /* kill old DNS cache entries */
 
3324
 
2315
3325
  /* this calls the protocol-specific function pointer previously set */
2316
3326
  if(conn->curl_done)
2317
3327
    result = conn->curl_done(conn);
2322
3332
 
2323
3333
  /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
2324
3334
     forced us to close this no matter what we think.
2325
 
    
 
3335
 
2326
3336
     if conn->bits.close is TRUE, it means that the connection should be
2327
3337
     closed in spite of all our efforts to be nice, due to protocol
2328
3338
     restrictions in our or the server's end */
2329
 
  if(data->set.reuse_forbid ||
2330
 
     ((CURLE_OK == result) && conn->bits.close))
2331
 
    result = Curl_disconnect(conn); /* close the connection */
 
3339
  if(data->set.reuse_forbid || conn->bits.close) {
 
3340
    CURLcode res2;
 
3341
    res2 = Curl_disconnect(conn); /* close the connection */
 
3342
 
 
3343
    /* If we had an error already, make sure we return that one. But
 
3344
       if we got a new error, return that. */
 
3345
    if(!result && res2)
 
3346
      result = res2;
 
3347
  }
2332
3348
  else
2333
3349
    infof(data, "Connection #%d left intact\n", conn->connectindex);
2334
3350
 
2341
3357
  struct connectdata *conn = *connp;
2342
3358
  struct SessionHandle *data=conn->data;
2343
3359
 
 
3360
  conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */
 
3361
 
2344
3362
  if(conn->curl_do) {
2345
3363
    /* generic protocol-specific function pointer set in curl_connect() */
2346
3364
    result = conn->curl_do(conn);
2347
3365
 
2348
3366
    /* This was formerly done in transfer.c, but we better do it here */
2349
 
    
2350
 
    if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) {
 
3367
 
 
3368
    if((CURLE_SEND_ERROR == result) && conn->bits.reuse) {
2351
3369
      /* This was a re-use of a connection and we got a write error in the
2352
3370
       * DO-phase. Then we DISCONNECT this connection and have another attempt
2353
3371
       * to CONNECT and then DO again! The retry cannot possibly find another
2356
3374
 
2357
3375
      infof(data, "Re-used connection seems dead, get a new one\n");
2358
3376
 
2359
 
      conn->bits.close = TRUE; /* enforce close of this connetion */
 
3377
      conn->bits.close = TRUE; /* enforce close of this connection */
2360
3378
      result = Curl_done(conn);   /* we are so done with this */
 
3379
 
 
3380
      /* conn is no longer a good pointer */
 
3381
 
2361
3382
      if(CURLE_OK == result) {
 
3383
        bool async;
2362
3384
        /* Now, redo the connect and get a new connection */
2363
 
        result = Curl_connect(data, connp);
2364
 
        if(CURLE_OK == result)
 
3385
        result = Curl_connect(data, connp, &async);
 
3386
        if(CURLE_OK == result) {
 
3387
          /* We have connected or sent away a name resolve query fine */
 
3388
 
 
3389
          conn = *connp; /* setup conn to again point to something nice */
 
3390
          if(async) {
 
3391
            /* Now, if async is TRUE here, we need to wait for the name
 
3392
               to resolve */
 
3393
            result = Curl_wait_for_resolv(conn, NULL);
 
3394
            if(result)
 
3395
              return result;
 
3396
            
 
3397
            /* Resolved, continue with the connection */
 
3398
            result = Curl_async_resolved(conn);              
 
3399
            if(result)
 
3400
              return result;
 
3401
          }
 
3402
          
2365
3403
          /* ... finally back to actually retry the DO phase */
2366
 
          result = conn->curl_do(*connp);
 
3404
          result = conn->curl_do(conn);
 
3405
        }
2367
3406
      }
2368
3407
    }
2369
3408
  }
2370
3409
  return result;
2371
3410
}
2372
3411
 
2373
 
/*
2374
 
 * local variables:
2375
 
 * eval: (load-file "../curl-mode.el")
2376
 
 * end:
2377
 
 * vim600: fdm=marker
2378
 
 * vim: et sw=2 ts=2 sts=2 tw=78
2379
 
 */
 
3412
CURLcode Curl_do_more(struct connectdata *conn)
 
3413
{
 
3414
  CURLcode result=CURLE_OK;
 
3415
 
 
3416
  if(conn->curl_do_more)
 
3417
    result = conn->curl_do_more(conn);
 
3418
 
 
3419
  return result;
 
3420
}
 
3421
 
 
3422
static bool safe_strequal(char* str1, char* str2)
 
3423
{
 
3424
  if(str1 && str2)
 
3425
    /* both pointers point to something then compare them */
 
3426
    return strequal(str1, str2);
 
3427
  else
 
3428
    /* if both pointers are NULL then treat them as equal */
 
3429
    return (!str1 && !str2);
 
3430
}
 
3431
 
 
3432
bool
 
3433
Curl_ssl_config_matches(struct ssl_config_data* data,
 
3434
                        struct ssl_config_data* needle)
 
3435
{
 
3436
  if((data->version == needle->version) &&
 
3437
     (data->verifypeer == needle->verifypeer) &&
 
3438
     (data->verifyhost == needle->verifyhost) &&
 
3439
     safe_strequal(data->CApath, needle->CApath) &&
 
3440
     safe_strequal(data->CAfile, needle->CAfile) &&
 
3441
     safe_strequal(data->random_file, needle->random_file) &&
 
3442
     safe_strequal(data->egdsocket, needle->egdsocket) &&
 
3443
     safe_strequal(data->cipher_list, needle->cipher_list))
 
3444
    return TRUE;
 
3445
 
 
3446
  return FALSE;
 
3447
}
 
3448
 
 
3449
bool
 
3450
Curl_clone_ssl_config(struct ssl_config_data *source,
 
3451
                      struct ssl_config_data *dest)
 
3452
{
 
3453
  dest->verifyhost = source->verifyhost;
 
3454
  dest->verifypeer = source->verifypeer;
 
3455
  dest->version = source->version;
 
3456
 
 
3457
  if(source->CAfile) {
 
3458
    dest->CAfile = strdup(source->CAfile);
 
3459
    if(!dest->CAfile)
 
3460
      return FALSE;
 
3461
  }
 
3462
 
 
3463
  if(source->CApath) {
 
3464
    dest->CApath = strdup(source->CApath);
 
3465
    if(!dest->CApath)
 
3466
      return FALSE;
 
3467
  }
 
3468
 
 
3469
  if(source->cipher_list) {
 
3470
    dest->cipher_list = strdup(source->cipher_list);
 
3471
    if(!dest->cipher_list)
 
3472
      return FALSE;
 
3473
  }
 
3474
 
 
3475
  if(source->egdsocket) {
 
3476
    dest->egdsocket = strdup(source->egdsocket);
 
3477
    if(!dest->egdsocket)
 
3478
      return FALSE;
 
3479
  }
 
3480
 
 
3481
  if(source->random_file) {
 
3482
    dest->random_file = strdup(source->random_file);
 
3483
    if(!dest->random_file)
 
3484
      return FALSE;
 
3485
  }
 
3486
 
 
3487
  return TRUE;
 
3488
}
 
3489
 
 
3490
void Curl_free_ssl_config(struct ssl_config_data* sslc)
 
3491
{
 
3492
  if(sslc->CAfile)
 
3493
    free(sslc->CAfile);
 
3494
 
 
3495
  if(sslc->CApath)
 
3496
    free(sslc->CApath);
 
3497
 
 
3498
  if(sslc->cipher_list)
 
3499
    free(sslc->cipher_list);
 
3500
 
 
3501
  if(sslc->egdsocket)
 
3502
    free(sslc->egdsocket);
 
3503
 
 
3504
  if(sslc->random_file)
 
3505
    free(sslc->random_file);
 
3506
}