1
/*****************************************************************************
3
* Project ___| | | | _ \| |
5
* | (__| |_| | _ <| |___
1
/***************************************************************************
3
* Project ___| | | | _ \| |
5
* | (__| |_| | _ <| |___
6
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
8
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
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
***************************************************************************/
24
24
/* -- WIN32 approved -- */
179
209
if(data->change.url_alloc)
180
210
free(data->change.url);
182
if(data->state.headerbuff)
183
free(data->state.headerbuff);
212
Curl_safefree(data->state.headerbuff);
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);
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);
223
if( !data->share || (data->cookies != data->share->cookies) ) {
224
Curl_cookie_cleanup(data->cookies);
226
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
191
229
/* free the connection cache */
192
230
free(data->state.connects);
194
if(data->info.contenttype)
195
free(data->info.contenttype);
232
Curl_safefree(data->info.contenttype);
234
Curl_digest_cleanup(data);
237
/* this destroys the channel and we cannot use it anymore after this */
238
ares_destroy(data->state.areschannel);
241
/* No longer a dirty share, if it exists */
243
data->share->dirty--;
202
int my_getpass(void *clientp, const char *prompt, char* buffer, int buflen )
205
clientp=NULL; /* prevent compiler warning */
207
retbuf = getpass_r(prompt, buffer, buflen);
211
return 0; /* success */
252
* @param curl is a pointer to a sessionhandle pointer that gets set by this
215
257
CURLcode Curl_open(struct SessionHandle **curl)
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 */
257
306
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
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;
263
312
/* Set the default size of the SSL session ID cache */
264
313
data->set.ssl.numsessions = 5;
315
data->set.proxyport = 1080;
317
data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
319
data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic authentication */
320
data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic authentication */
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);
271
327
if(!data->state.connects) {
328
free(data->state.headerbuff);
273
330
return CURLE_OUT_OF_MEMORY;
334
* libcurl 7.10 introduces SSL verification *by default*! This needs to be
335
* switched off unless wanted.
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;
276
344
memset(data->state.connects, 0,
277
345
sizeof(struct connectdata *)*data->state.numconnects);
493
595
data->set.ssl.version = va_arg(param, long);
598
case CURLOPT_COOKIESESSION:
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
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
611
* We run mostly with the original cookie spec, as hardly anyone implements
614
data->set.cookiesession = (bool)va_arg(param, long);
617
#ifndef CURL_DISABLE_HTTP
496
618
case CURLOPT_COOKIEFILE:
498
620
* Set cookie file to read and parse. Can be used multiple times.
500
622
cookiefile = (char *)va_arg(param, void *);
502
data->cookies = Curl_cookie_init(cookiefile, data->cookies);
624
/* append the cookie file name to the list of file names, and deal with
626
data->change.cookielist =
627
curl_slist_append(data->change.cookielist, cookiefile);
505
630
case CURLOPT_COOKIEJAR:
724
878
data->set.useragent = va_arg(param, char *);
880
case CURLOPT_ENCODING:
882
* String to use at the value of Accept-Encoding header. 08/28/02 jhrg
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.
890
data->set.encoding = va_arg(param, char *);
891
if(data->set.encoding && !*data->set.encoding)
892
data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
895
case CURLOPT_HTTPAUTH:
897
* Set HTTP Authentication type BITMASK.
900
long auth = va_arg(param, long);
901
/* switch off bits we can't support */
903
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
906
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
909
return CURLE_FAILED_INIT; /* no supported types left! */
911
data->set.httpauth = auth;
915
case CURLOPT_PROXYAUTH:
917
* Set HTTP Authentication type BITMASK.
920
long auth = va_arg(param, long);
921
/* switch off bits we can't support */
923
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
926
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
929
return CURLE_FAILED_INIT; /* no supported types left! */
931
data->set.proxyauth = auth;
726
935
case CURLOPT_USERPWD:
728
937
* user:password to use in the operation
937
1187
data->set.telnet_options = va_arg(param, struct curl_slist *);
1190
case CURLOPT_BUFFERSIZE:
1192
* The application kindly asks for a differently sized receive buffer.
1193
* If it seems reasonable, we'll use it.
1195
data->set.buffer_size = va_arg(param, long);
1197
if((data->set.buffer_size> (BUFSIZE -1 )) ||
1198
(data->set.buffer_size < 1))
1199
data->set.buffer_size = 0; /* huge internal default */
1203
case CURLOPT_NOSIGNAL:
1205
* The application asks not to set any signal() or alarm() handlers,
1206
* even when using a timeout.
1208
data->set.no_signal = va_arg(param, long) ? TRUE : FALSE;
1213
struct Curl_share *set;
1214
set = va_arg(param, struct Curl_share *);
1216
/* disconnect from old share, if any */
1218
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1220
if(data->share->hostcache == data->hostcache)
1221
data->hostcache = NULL;
1223
if(data->share->cookies == data->cookies)
1224
data->cookies = NULL;
1226
data->share->dirty--;
1228
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1232
/* use new share if it set */
1236
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1238
data->share->dirty++;
1240
if(data->share->hostcache) {
1241
/* use shared host cache, first free own one if any */
1243
Curl_hash_destroy(data->hostcache);
1245
data->hostcache = data->share->hostcache;
1248
if(data->share->cookies) {
1249
/* use shared cookie list, first free own one if any */
1251
Curl_cookie_cleanup(data->cookies);
1252
data->cookies = data->share->cookies;
1255
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1259
/* check cookie list is set */
1261
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE );
1263
/* check for host cache not needed,
1264
* it will be done by curl_easy_perform */
1268
case CURLOPT_PROXYTYPE:
1270
* Set proxy type. HTTP/SOCKS4/SOCKS5
1272
data->set.proxytype = (curl_proxytype)va_arg(param, long);
1275
case CURLOPT_PRIVATE:
1277
* Set private data pointer.
1279
data->set.private = va_arg(param, char *);
1282
case CURLOPT_HTTP200ALIASES:
1284
* Set a list of aliases for HTTP 200 in response header
1286
data->set.http200aliases = va_arg(param, struct curl_slist *);
1289
case CURLOPT_MAXFILESIZE:
1291
* Set the maximum size of a file to download.
1293
data->set.max_filesize = va_arg(param, long);
1296
case CURLOPT_FTP_SSL:
1298
* Make FTP transfers attempt to use SSL/TLS.
1300
data->set.ftp_ssl = (curl_ftpssl)va_arg(param, long);
1303
case CURLOPT_IPRESOLVE:
1304
data->set.ip_version = va_arg(param, long);
1307
case CURLOPT_MAXFILESIZE_LARGE:
1309
* Set the maximum size of a file to download.
1311
data->set.max_filesize = va_arg(param, curl_off_t);
1314
case CURLOPT_TCP_NODELAY:
1316
* Enable or disable TCP_NODELAY, which will disable/enable the Nagle
1319
data->set.tcp_nodelay = (bool)va_arg(param, long);
940
1323
/* unknown tag and its companion, just ignore: */
941
return CURLE_READ_ERROR; /* correct this */
1324
return CURLE_FAILED_INIT; /* correct this */
943
1326
return CURLE_OK;
958
1341
conn->bits.rangestringalloc = FALSE;
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
1349
conn->data->state.authstage = 0;
1351
if(conn->curl_disconnect)
1352
/* This is set if protocol-specific cleanups should be made */
1353
conn->curl_disconnect(conn);
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;
967
if(conn->curl_disconnect)
968
/* This is set if protocol-specific cleanups should be made */
969
conn->curl_disconnect(conn);
971
if(conn->proto.generic)
972
free(conn->proto.generic);
977
if(conn->path) /* the URL path part */
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 */
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);
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);
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]);
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);
1393
Curl_free_ssl_config(&conn->ssl_config);
1008
1395
free(conn); /* free all the connection oriented data */
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) ) {
1074
if(strequal(needle->protostr, "FTP")) {
1075
/* This is FTP, verify that we're using the same name and
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)) {
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 */
1083
dead = SocketIsDead(check->firstsocket);
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.
1090
* This is now subject to discussion. What do you think?
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 */
1096
/* There's no need to continue search, because we only store
1097
one connection for each unique set of identifiers */
1102
return TRUE; /* yes, we found one to use! */
1106
1488
else { /* The requested needle connection is using a proxy,
1216
static CURLcode ConnectPlease(struct connectdata *conn)
1615
* This function logs in to a SOCKS5 proxy and sends the specifies the final
1616
* desitination server.
1618
static int handleSock5Proxy(const char *proxy_name,
1619
const char *proxy_password,
1620
struct connectdata *conn)
1623
According to the RFC1928, section "6. Replies". This is what a SOCK5
1626
+----+-----+-------+------+----------+----------+
1627
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
1628
+----+-----+-------+------+----------+----------+
1629
| 1 | 1 | X'00' | 1 | Variable | 2 |
1630
+----+-----+-------+------+----------+----------+
1634
o VER protocol version: X'05'
1639
unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
1644
int sock = conn->sock[FIRSTSOCKET];
1646
Curl_nonblock(sock, FALSE);
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 */
1653
code = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
1655
if ((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
1656
failf(conn->data, "Unable to send initial SOCKS5 request.");
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.");
1666
if (socksreq[0] != 5) {
1667
failf(conn->data, "Received invalid version in initial SOCKS5 response.");
1670
if (socksreq[1] == 0) {
1671
/* Nothing to do, no authentication needed */
1674
else if (socksreq[1] == 2) {
1675
/* Needs user name and password */
1676
int userlen, pwlen, len;
1678
userlen = strlen(proxy_name);
1679
pwlen = proxy_password?strlen(proxy_password):0;
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
* +----+------+----------+------+----------+
1689
socksreq[len++] = 1; /* username/pw subnegotiation version */
1690
socksreq[len++] = (char) userlen;
1691
memcpy(socksreq + len, proxy_name, (int) userlen);
1693
socksreq[len++] = (char) pwlen;
1694
memcpy(socksreq + len, proxy_password, (int) pwlen);
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.");
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.");
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]);
1716
/* Everything is good so far, user was authenticated! */
1720
if (socksreq[1] == 1) {
1722
"SOCKS5 GSSAPI per-message authentication is not supported.");
1725
else if (socksreq[1] == 255) {
1726
if (proxy_name[0] == 0) {
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.)");
1733
failf(conn->data, "No authentication method was acceptable.");
1739
"Undocumented SOCKS5 mode attempted to be used by server.");
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 */
1752
struct Curl_dns_entry *dns;
1753
Curl_addrinfo *hp=NULL;
1754
int rc = Curl_resolv(conn, conn->hostname, conn->remote_port, &dns);
1760
/* this requires that we're in "wait for resolve" state */
1761
rc = Curl_wait_for_resolv(conn, &dns);
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.
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];
1775
Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */
1778
failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.",
1784
"%s:%d has an internal error an needs to be fixed to work",
1785
__FILE__, __LINE__);
1790
*((unsigned short*)&socksreq[8]) = htons(conn->remote_port);
1793
const int packetsize = 10;
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.");
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.");
1807
if (socksreq[0] != 5) { /* version */
1809
"SOCKS5 reply has wrong version, version should be 5.");
1812
if (socksreq[1] != 0) { /* Anything besides 0 is an error */
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])),
1823
Curl_nonblock(sock, TRUE);
1824
return 0; /* Proxy was successful! */
1827
static CURLcode ConnectPlease(struct connectdata *conn,
1828
struct Curl_dns_entry *hostaddr,
1218
1831
CURLcode result;
1219
1832
Curl_ipconnect *addr;
1222
1835
* Connect to server/proxy
1223
1836
*************************************************************/
1224
1837
result= Curl_connecthost(conn,
1840
&conn->sock[FIRSTSOCKET],
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;
1233
1849
#ifdef ENABLE_IPV6
1234
1850
conn->serv_addr = addr;
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);
1859
if (conn->data->set.proxytype == CURLPROXY_SOCKS5) {
1860
return handleSock5Proxy(conn->proxyuser,
1863
CURLE_COULDNT_CONNECT : CURLE_OK;
1865
else if (conn->data->set.proxytype == CURLPROXY_HTTP) {
1866
/* do nothing here. handled later. */
1869
failf(conn->data, "unknown proxytype option given");
1870
return CURLE_COULDNT_CONNECT;
1878
* ALERT! The 'dns' pointer being passed in here might be NULL at times.
1880
static void verboseconnect(struct connectdata *conn,
1881
struct Curl_dns_entry *dns)
1883
struct SessionHandle *data = conn->data;
1885
/* Figure out the ip-number and display the first host name it shows: */
1888
char hbuf[NI_MAXHOST];
1889
#ifdef HAVE_NI_WITHSCOPEID
1890
#define NIFLAGS NI_NUMERICHOST | NI_WITHSCOPEID
1892
#define NIFLAGS NI_NUMERICHOST
1895
struct addrinfo *ai = dns->addr;
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
1900
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
1902
snprintf(hbuf, sizeof(hbuf), "unknown");
1905
if (ai->ai_canonname) {
1906
infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
1913
snprintf(hbuf, sizeof(hbuf), "same host");
1916
infof(data, "Connected to %s port %d\n", hbuf, conn->port);
1920
#ifdef HAVE_INET_NTOA_R
1923
Curl_addrinfo *hostaddr=dns?dns->addr:NULL;
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)),
1939
* We have discovered that the TCP connection has been successful, we can now
1940
* proceed with some action.
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.
1948
CURLcode Curl_protocol_connect(struct connectdata *conn,
1949
struct Curl_dns_entry *hostaddr)
1951
struct SessionHandle *data = conn->data;
1952
CURLcode result=CURLE_OK;
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
1960
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
1962
if(data->set.verbose)
1963
verboseconnect(conn, hostaddr);
1965
if(conn->curl_connect) {
1966
/* is there a protocol-specific connect() procedure? */
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();
1973
/* Call the protocol-specific connect function */
1974
result = conn->curl_connect(conn);
1977
return result; /* pass back status */
1981
* CreateConnection() sets up a new connectdata struct, or re-uses an already
1982
* existing one, and resolves host name.
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
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
1993
* @see SetupConnection()
1247
1996
static CURLcode CreateConnection(struct SessionHandle *data,
1248
struct connectdata **in_connect)
1997
struct connectdata **in_connect,
1998
struct Curl_dns_entry **addr,
1252
2002
CURLcode result=CURLE_OK;
1253
2003
char resumerange[40]="";
1254
2004
struct connectdata *conn;
1255
2005
struct connectdata *conn_temp;
2007
struct Curl_dns_entry *hostaddr;
2009
unsigned int prev_alarm=0;
1256
2011
char endbracket;
1258
#ifdef HAVE_INET_NTOA_R
1262
unsigned int prev_alarm;
2012
char user[MAX_CURL_USER_LENGTH];
2013
char passwd[MAX_CURL_PASSWORD_LENGTH];
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? */
1269
2021
#ifdef HAVE_SIGNAL
1270
2022
void *keep_sigact; /* store the old handler here */
2026
*addr = NULL; /* nothing yet */
1274
2029
/*************************************************************
1275
2030
* Check input data
1276
2031
*************************************************************/
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 */
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;
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;
1318
2068
/* maxdownload must be -1 on init, as 0 is a valid value! */
1319
2069
conn->maxdownload = -1; /* might have been used previously! */
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, "/");
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.
1391
2177
if (2 > sscanf(data->change.url,
1392
"%64[^\n:]://%512[^\n/]%[^\n]",
1393
conn->protostr, conn->gname, conn->path)) {
2178
"%64[^\n:]://%[^\n/?]%[^\n]",
2180
conn->namebuffer, conn->path)) {
1396
2183
* The URL was badly formatted, let's try the browser-style _without_
1397
2184
* protocol specified like 'http://'.
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)) ) {
1402
2189
* We couldn't even get this format.
1410
2197
* is based on the first letters of the server name.
1413
if(strnequal(conn->gname, "FTP", 3)) {
1414
strcpy(conn->protostr, "ftp");
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! */
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");
1431
2220
strcpy(conn->protostr, "http");
1438
buf = data->state.buffer; /* this is our buffer */
1440
/*************************************************************
1441
* Take care of user and password authentication stuff
1442
*************************************************************/
1444
if(conn->bits.user_passwd && !data->set.use_netrc) {
1445
data->state.user[0] =0;
1446
data->state.passwd[0]=0;
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);
1454
/* no name given, get the password only */
1455
sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd);
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;
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
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] = '/';
2240
* So if the URL was A://B/C,
2241
* conn->protostr is A
2242
* conn->namebuffer is B
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;
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);
1480
/* no name given, get the password only */
1481
sscanf(data->set.proxyuserpwd+1, "%127[^\n]", data->state.proxypasswd);
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,
1488
data->state.proxypasswd,
1489
sizeof(data->state.proxypasswd)))
1490
return CURLE_BAD_PASSWORD_ENTERED;
2250
char proxyuser[MAX_CURL_USER_LENGTH]="";
2251
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
2253
sscanf(data->set.proxyuserpwd,
2254
"%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
2255
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
2256
proxyuser, proxypasswd);
2258
conn->proxyuser = strdup(proxyuser);
2259
if(!conn->proxyuser)
2260
return CURLE_OUT_OF_MEMORY;
2262
conn->proxypasswd = strdup(proxypasswd);
2263
if(!conn->proxypasswd)
2264
return CURLE_OUT_OF_MEMORY;
1495
2267
/*************************************************************
1496
* Set a few convenience pointers
1497
*************************************************************/
1498
conn->name = conn->gname;
1499
conn->ppath = conn->path;
1500
conn->hostname = conn->name;
1503
/*************************************************************
1504
2268
* Detect what (if any) proxy to use
1505
2269
*************************************************************/
1506
2270
if(!data->change.proxy) {
1594
2365
if(proxy && *proxy) {
1595
2366
/* we have a proxy here to set */
2368
char proxyuser[MAX_CURL_USER_LENGTH];
2369
char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
2373
/* skip the possible protocol piece */
2374
ptr=strstr(proxy, "://");
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);
2392
if(!conn->proxyuser)
2393
return CURLE_OUT_OF_MEMORY;
2395
Curl_safefree(conn->proxypasswd);
2396
conn->proxypasswd = strdup(proxypasswd);
2398
if(!conn->proxypasswd)
2399
return CURLE_OUT_OF_MEMORY;
2401
conn->bits.proxy_user_passwd = TRUE; /* enable it */
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 */
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;
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 "-",
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 */
1644
2459
/*************************************************************
1645
2460
* Setup internals depending on protocol
1646
2461
*************************************************************/
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;
2474
failf(data, LIBCURL_NAME
2475
" was built with HTTP disabled, http: not supported!");
2476
return CURLE_UNSUPPORTED_PROTOCOL;
1657
2479
else if (strequal(conn->protostr, "HTTPS")) {
2480
#if defined(USE_SSLEAY) && !defined(CURL_DISABLE_HTTP)
1660
2482
conn->port = (data->set.use_port && data->state.allow_port)?
1661
2483
data->set.use_port:PORT_HTTPS;
1673
2496
#endif /* !USE_SSLEAY */
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;
2505
conn->path = strchr(&conn->path[1], '/');
2506
if (conn->path == NULL)
2507
conn->path = conn->pathbuffer;
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;
2514
failf(data, LIBCURL_NAME
2515
" was built with GOPHER disabled, gopher: not supported!");
1689
2518
else if(strequal(conn->protostr, "FTP") ||
1690
2519
strequal(conn->protostr, "FTPS")) {
2522
#ifndef CURL_DISABLE_FTP
2524
int port = PORT_FTP;
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 */
1697
2532
failf(data, LIBCURL_NAME
1698
2533
" was built with SSL disabled, ftps: not supported!");
1715
2551
failf(data, "ftps does not work through http proxy!");
1716
2552
return CURLE_UNSUPPORTED_PROTOCOL;
2554
#ifndef CURL_DISABLE_HTTP
1718
2555
conn->curl_do = Curl_http;
1719
2556
conn->curl_done = Curl_http_done;
2558
failf(data, "FTP over http proxy requires HTTP support built-in!");
2559
return CURLE_UNSUPPORTED_PROTOCOL;
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;
1728
conn->ppath++; /* don't include the initial slash */
2570
conn->path++; /* don't include the initial slash */
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=");
1734
type=strstr(conn->gname, ";type=");
2576
type=strstr(conn->namebuffer, ";type=");
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;
1761
2611
conn->remote_port = PORT_TELNET;
1762
2612
conn->curl_do = Curl_telnet;
1763
2613
conn->curl_done = Curl_telnet_done;
2615
failf(data, LIBCURL_NAME
2616
" was built with TELNET disabled!");
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 */
2628
failf(data, LIBCURL_NAME
2629
" was built with DICT disabled!");
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 */
2641
failf(data, LIBCURL_NAME
2642
" was built with LDAP disabled!");
1781
2645
else if (strequal(conn->protostr, "FILE")) {
2646
#ifndef CURL_DISABLE_FILE
1782
2647
conn->protocol |= PROT_FILE;
1784
2649
conn->curl_do = Curl_file;
1806
2676
/*************************************************************
1807
* .netrc scanning coming up
1808
*************************************************************/
1809
if(data->set.use_netrc) {
1810
if(Curl_parsenetrc(conn->hostname,
1812
data->state.passwd)) {
1813
infof(data, "Couldn't find host %s in the .netrc file, using defaults",
1817
conn->bits.user_passwd = 1; /* enable user+password */
1819
/* weather we failed or not, we don't know which fields that were filled
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);
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 @ */
1836
data->state.user[0] =0;
1837
data->state.passwd[0]=0;
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);
1845
/* no name given, get the password only */
1846
sscanf(conn->name+1, "%127[^@]", data->state.passwd);
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);
1853
/* if the new name is longer than accepted, then just use
1854
the unconverted name, it'll be wrong but what the heck */
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;
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);
1876
conn->bits.user_passwd=TRUE; /* enable user+password */
1879
strcpy(data->state.user, CURL_DEFAULT_USER);
1880
strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
1884
/*************************************************************
1885
2677
* Figure out the remote port number
1887
2679
* No matter if we use a proxy or not, we have to figure out the remote
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)
2685
* The conn->hostname is currently [user:passwd@]host[:port] where host
2686
* could be a hostname, IPv4 address or IPv6 address.
1892
2687
*************************************************************/
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;
1900
tmp = strchr(conn->name, ']');
2693
conn->hostname++; /* pass the starting bracket */
2694
tmp = strchr(conn->hostname, ']');
1901
2695
*tmp = 0; /* zero terminate */
1903
2696
tmp++; /* pass the ending bracket */
1904
2697
if(':' != *tmp)
1905
2698
tmp = NULL; /* no port number available */
1908
/* traditional IPv4-style port-extracting */
1909
tmp = strchr(conn->name, ':');
2701
tmp = strrchr(conn->hostname, ':');
1913
*tmp++ = '\0'; /* cut off the name there */
1914
conn->remote_port = atoi(tmp);
2707
port=strtoul(tmp+1, &rest, 10); /* Port number must be decimal */
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 */
2713
if (port > 0xffff) { /* Single unix standard says port numbers are
2715
failf(data, "Port number too large: %lu", port);
2716
return CURLE_URL_MALFORMAT;
2719
*tmp = '\0'; /* cut off the name there */
2720
conn->remote_port = (unsigned short)port;
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. */
1968
2775
/*************************************************************
2776
* Take care of user and password authentication stuff
2777
*************************************************************/
2780
* Inputs: data->set.userpwd (CURLOPT_USERPWD)
2781
* data->set.fpasswd (CURLOPT_PASSWDFUNCTION)
2782
* data->set.use_netrc (CURLOPT_NETRC)
2785
* hard-coded defaults
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
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
2798
* We need somewhere to put the embedded details, so do that first.
2801
user[0] =0; /* to make everything well-defined */
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;
2811
/* there's a user+password given here, to the left of the @ */
2813
conn->hostname = ++ptr;
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 :-(
2821
if (data->set.use_netrc != CURL_NETRC_REQUIRED) {
2822
/* We could use the one in the URL */
2824
conn->bits.user_passwd = 1; /* enable user+password */
2826
if(*userpass != ':') {
2827
/* the name is given, get user+password */
2828
sscanf(userpass, "%127[^:@]:%127[^@]",
2832
/* no name given, get the password only */
2833
sscanf(userpass, ":%127[^@]", passwd);
2836
char *newname=curl_unescape(user, 0);
2837
if(strlen(newname) < sizeof(user)) {
2838
strcpy(user, newname);
2840
/* if the new name is longer than accepted, then just use
2841
the unconverted name, it'll be wrong but what the heck */
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);
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.
2862
* user_password is set in "inherite initial knowledge' above,
2863
* so it doesn't have to be set in this block
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]",
2873
if (data->set.use_netrc != CURL_NETRC_IGNORED) {
2874
if(Curl_parsenetrc(conn->hostname,
2876
data->set.netrc_file)) {
2877
infof(data, "Couldn't find host %s in the .netrc file, using defaults\n",
2881
conn->bits.user_passwd = 1; /* enable user+password */
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) {
2888
conn->user = strdup(CURL_DEFAULT_USER);
2889
conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
2891
/* This is the default password, so DON'T set conn->bits.user_passwd */
2894
/* store user + password, zero-length if not set */
2895
conn->user = strdup(user);
2896
conn->passwd = strdup(passwd);
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
1972
2903
*************************************************************/
1974
/* reuse_fresh is set TRUE if we are told to use a fresh connection
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;
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)
2917
reuse = ConnectionExists(data, conn, &conn_temp);
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.
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 */
1987
2928
if(old_conn->proxyhost)
1988
2929
free(old_conn->proxyhost);
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);
1989
2935
conn = conn_temp; /* use this connection from now on */
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];
1995
free(conn->path); /* free the previously allocated path pointer */
1997
/* 'path' points to the allocated data, 'ppath' may have been advanced
1998
to point somewhere within the 'path' area. */
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;
2942
/* get the newly set value, not the old one */
2943
conn->bits.no_body = old_conn->bits.no_body;
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;
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;
2002
2953
/* re-use init */
2003
2954
conn->bits.reuse = TRUE; /* yes, we're re-using here */
2041
3003
ConnectionStore(data, conn);
3006
/* Continue connectdata initialization here.
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;
3013
conn->bits.upload_chunky =
3014
((conn->protocol&PROT_HTTP) &&
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 */
3020
/* else, no chunky upload */
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
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
*************************************************************/
2053
3035
#ifdef HAVE_SIGACTION
2054
3036
struct sigaction sigact;
2055
3037
sigaction(SIGALRM, NULL, &sigact);
2084
3066
recently set in the beginning of this function and nothing slow
2085
3067
has been done since then until now. */
3069
#endif /* SIGALRM */
3071
#endif /* USE_ARES */
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 */
3079
conn->connect_addr = NULL; /* we don't connect now so we don't have any
3080
fresh connect_addr struct to point to */
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 */
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);
2103
if(!conn->hostaddr) {
2104
failf(data, "Couldn't resolve host '%s'", conn->name);
3088
rc = Curl_resolv(conn, conn->hostname, conn->port, &hostaddr);
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 */
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. */
3099
/* This is a proxy that hasn't been resolved yet. */
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);
2118
if(!conn->hostaddr) {
3102
rc = Curl_resolv(conn, conn->proxyhost, conn->port, &hostaddr);
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 */
2124
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
2126
if(data->set.timeout || data->set.connecttimeout) {
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
2161
3152
alarm(0); /* just shut it off */
3159
/* SetupConnection() should be called after the name resolve initiated in
3160
* CreateConnection() is all done.
3163
static CURLcode SetupConnection(struct connectdata *conn,
3164
struct Curl_dns_entry *hostaddr)
3166
struct SessionHandle *data = conn->data;
3167
CURLcode result=CURLE_OK;
3169
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
3171
if(conn->protocol & PROT_FILE)
3172
/* There's nothing in this function to setup if we're only doing
3173
a file:// transfer */
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);
2184
/*************************************************************
2185
3177
* Send user-agent to HTTP proxies even if the target protocol
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);
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);
3195
conn->bytecount = 0;
3196
conn->headerbytecount = 0;
3198
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
2198
3201
/* Connect only if not already connected! */
2199
result = ConnectPlease(conn);
3202
result = ConnectPlease(conn, hostaddr, &connected);
3205
result = Curl_protocol_connect(conn, hostaddr);
3206
if(CURLE_OK == result)
3207
conn->bits.tcpconnect = TRUE;
3210
conn->bits.tcpconnect = FALSE;
2200
3213
if(CURLE_OK != result)
2203
if(conn->curl_connect) {
2204
/* is there a connect() procedure? */
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();
2211
/* Call the protocol-specific connect function */
2212
result = conn->curl_connect(conn);
2213
if(result != CURLE_OK)
2214
return result; /* pass back errors */
2218
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected */
2220
conn->now = Curl_tvnow(); /* time this *after* the connect is done */
2221
conn->bytecount = 0;
2222
conn->headerbytecount = 0;
2224
/* Figure out the ip-number and display the first host name it shows: */
2227
char hbuf[NI_MAXHOST];
2228
#ifdef NI_WITHSCOPEID
2229
const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
2231
const int niflags = NI_NUMERICHOST;
2233
struct addrinfo *ai = conn->serv_addr;
2235
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
2237
snprintf(hbuf, sizeof(hbuf), "?");
2239
if (ai->ai_canonname) {
2240
infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf,
2243
infof(data, "Connected to %s port %d\n", hbuf, conn->port);
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))
3217
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
3218
conn->bits.tcpconnect = TRUE;
3219
if(data->set.verbose)
3220
verboseconnect(conn, hostaddr);
3223
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
3224
set this here perhaps a second time */
2261
3227
/* 20000330 mgs
2275
3241
CURLcode Curl_connect(struct SessionHandle *data,
2276
struct connectdata **in_connect)
3242
struct connectdata **in_connect,
2279
struct connectdata *conn;
3246
struct Curl_dns_entry *dns;
3248
*asyncp = FALSE; /* assume synchronous resolves by default */
2281
3250
/* call the stuff that needs to be called */
2282
code = CreateConnection(data, in_connect);
3251
code = CreateConnection(data, in_connect, &dns, asyncp);
3253
if(CURLE_OK == code) {
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);
3261
response will be received and treated async wise */
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;
2289
Curl_disconnect(conn); /* close the connection */
2290
*in_connect = NULL; /* return a NULL */
3268
Curl_disconnect(*in_connect); /* close the connection */
3269
*in_connect = NULL; /* return a NULL */
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)
3280
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME)
3281
CURLcode code = SetupConnection(conn, conn->async.dns);
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 */
2357
3375
infof(data, "Re-used connection seems dead, get a new one\n");
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 */
3380
/* conn is no longer a good pointer */
2361
3382
if(CURLE_OK == result) {
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 */
3389
conn = *connp; /* setup conn to again point to something nice */
3391
/* Now, if async is TRUE here, we need to wait for the name
3393
result = Curl_wait_for_resolv(conn, NULL);
3397
/* Resolved, continue with the connection */
3398
result = Curl_async_resolved(conn);
2365
3403
/* ... finally back to actually retry the DO phase */
2366
result = conn->curl_do(*connp);
3404
result = conn->curl_do(conn);
2375
* eval: (load-file "../curl-mode.el")
2377
* vim600: fdm=marker
2378
* vim: et sw=2 ts=2 sts=2 tw=78
3412
CURLcode Curl_do_more(struct connectdata *conn)
3414
CURLcode result=CURLE_OK;
3416
if(conn->curl_do_more)
3417
result = conn->curl_do_more(conn);
3422
static bool safe_strequal(char* str1, char* str2)
3425
/* both pointers point to something then compare them */
3426
return strequal(str1, str2);
3428
/* if both pointers are NULL then treat them as equal */
3429
return (!str1 && !str2);
3433
Curl_ssl_config_matches(struct ssl_config_data* data,
3434
struct ssl_config_data* needle)
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))
3450
Curl_clone_ssl_config(struct ssl_config_data *source,
3451
struct ssl_config_data *dest)
3453
dest->verifyhost = source->verifyhost;
3454
dest->verifypeer = source->verifypeer;
3455
dest->version = source->version;
3457
if(source->CAfile) {
3458
dest->CAfile = strdup(source->CAfile);
3463
if(source->CApath) {
3464
dest->CApath = strdup(source->CApath);
3469
if(source->cipher_list) {
3470
dest->cipher_list = strdup(source->cipher_list);
3471
if(!dest->cipher_list)
3475
if(source->egdsocket) {
3476
dest->egdsocket = strdup(source->egdsocket);
3477
if(!dest->egdsocket)
3481
if(source->random_file) {
3482
dest->random_file = strdup(source->random_file);
3483
if(!dest->random_file)
3490
void Curl_free_ssl_config(struct ssl_config_data* sslc)
3498
if(sslc->cipher_list)
3499
free(sslc->cipher_list);
3502
free(sslc->egdsocket);
3504
if(sslc->random_file)
3505
free(sslc->random_file);