Compare commits

...

81 Commits

Author SHA1 Message Date
Daniel Stenberg
6063dff8d0 Modified to not mix ordinary print to STDOUT with a system() that prints to
stdout, since I've found cases on Solaris where the second output mixes with
the first and thus the big check-script doesn't properly find the first
string in the output stream.
2005-04-18 05:46:10 +00:00
Daniel Stenberg
7fba9ed398 somewhat clarified that this only sets the fd_sets and expects them to be
cleared before this function is called
2005-04-17 23:01:46 +00:00
Daniel Stenberg
53280a196b keywords added 2005-04-16 23:15:19 +00:00
Daniel Stenberg
0bf9a5704b minor edits, report the test cases without keywords 2005-04-16 23:15:12 +00:00
Daniel Stenberg
8182d17ae1 starting to produce a summary in HTML 2005-04-16 12:43:32 +00:00
Daniel Stenberg
69b1ac7dcd avoid warning on windows 2005-04-16 12:30:01 +00:00
Daniel Stenberg
b15507aac3 clarify that > in the verbose output can contain newlines 2005-04-16 12:24:12 +00:00
Daniel Stenberg
6c2f583f51 keywords added 2005-04-16 00:00:35 +00:00
Daniel Stenberg
a72eaddda3 initial tool to report info/keywords of the test cases 2005-04-15 23:48:58 +00:00
Daniel Stenberg
dc050e45df started adding "keywords" for each test, to better allow us to sum up what
kind of tests we have and how many tests that test certain features
2005-04-15 23:48:31 +00:00
Daniel Stenberg
2fcbf13920 add needed include 2005-04-15 21:51:46 +00:00
Dominick Meglio
099ae31523 Attempted to fix c-ares not building on non-IPv6 systems 2005-04-15 15:25:16 +00:00
Daniel Stenberg
c2fcdf3a02 if libgnutls-config isn't found in the given path, deal with it nicer (but
it is still likely to not do very good since it can't figure out all the lib
dependencies)
2005-04-15 08:45:35 +00:00
Daniel Stenberg
2056a538b9 Two new slowdown tests for better testing of the FTP response reader function
when the response come in many small chunks.
2005-04-14 22:52:42 +00:00
Daniel Stenberg
cd1144dc24 make the ftp server support reply/servercmd, and make SLOWDOWN work, and
update the docs accordingly
2005-04-14 22:52:08 +00:00
Daniel Stenberg
e9d068b913 oops, only negative numbers are errors 2005-04-13 21:17:05 +00:00
Dan Fandrich
ec2ad57c32 Mention GnuTLS and fix a few spelling errors. 2005-04-13 19:31:00 +00:00
Daniel Stenberg
316adac511 don't bail out just because the ca file has a problem, it might be OK 2005-04-13 12:38:01 +00:00
Daniel Stenberg
d7b11d4c33 fix port number 2005-04-13 12:37:38 +00:00
Daniel Stenberg
c52aa6df33 GnuTLS support 2005-04-13 08:50:13 +00:00
Daniel Stenberg
a19b23b59f extended the multi-thread explanation 2005-04-13 08:47:59 +00:00
Daniel Stenberg
4e26b2a65b fix compiler warning 2005-04-13 06:52:03 +00:00
Dan Fandrich
7c4feac6db Allow environment variables to override default autotools. 2005-04-13 00:32:33 +00:00
Daniel Stenberg
e01e364c37 next release will be version 7.14.0 thanks to the added GnuTLS support 2005-04-12 14:17:07 +00:00
Daniel Stenberg
c13a3d7b84 Provides an unconditional strlcat() proto even if strlcat() was found by
configure. An attempt to fix warnings when we build and the strlcat() function
is provided by one if the libs (gss or krb4) since then we have no protos
for it in a system header.
2005-04-12 07:56:57 +00:00
Daniel Stenberg
67805b6dc5 requires OpenSSL, as our GnuTLS doesn't provide support for
CURLOPT_SSL_CTX_FUNCTION (yet).
2005-04-12 07:19:34 +00:00
Daniel Stenberg
0050ab2a3d support tests that requires 'OpenSSL' specificly 2005-04-12 07:18:48 +00:00
Daniel Stenberg
60e66c6cbf credits 2005-04-11 14:07:02 +00:00
Daniel Stenberg
5ad2a253e8 refresh 2005-04-11 13:50:19 +00:00
Daniel Stenberg
b5d50e9298 5.12 Can I make libcurl fake or hide my real IP address? 2005-04-11 13:39:55 +00:00
Daniel Stenberg
37f7362aca HTTP 304 response with Content-Length: header 2005-04-10 22:56:46 +00:00
Dominick Meglio
bee198def5 Removed usage of u_int and u_char 2005-04-09 23:46:31 +00:00
Daniel Stenberg
f09e479fd6 Blah, revert my removal of the extra check since the problem is there for real.
Archived thread of the help-gnutls mailing list regarding this problem:

http://lists.gnu.org/archive/html/help-gnutls/2005-04/msg00000.html

(and I _am_ sorry for my confused behaviour on this problem.)
2005-04-09 22:33:14 +00:00
Daniel Stenberg
80fe93bc33 OK, I must've been halucinating or something because I no longer see the
bug I thought I saw before when I changed this...!
2005-04-09 21:38:14 +00:00
Dominick Meglio
ea03ad3bee Made sortlist support IPv6 (this can probably use some testing) 2005-04-09 19:59:59 +00:00
Dominick Meglio
feec421744 Made sortlist support CIDR matching for IPv4 2005-04-09 16:49:47 +00:00
Dominick Meglio
634982840e Added preliminary IPv6 support to ares_gethostbyname 2005-04-08 19:46:46 +00:00
Daniel Stenberg
fb3c85ab2f fixed the 304 response-with-content-length problem reported by Cory Nelson 2005-04-08 16:59:13 +00:00
Dominick Meglio
a9b7c3531c Added include for inet_net_pton.h to ares__get_hostent.c 2005-04-08 16:22:51 +00:00
Dominick Meglio
a7ba0d908d Made ares_gethostbyaddr support IPv6 by specifying AF_INET6 as the family 2005-04-08 15:41:31 +00:00
Daniel Stenberg
2fc70e2c5d re-arrange some code to prevent warnings on unreachable code 2005-04-08 09:25:48 +00:00
Daniel Stenberg
7ae3f0e70c include sys/types.h too when checking for headers as otherwise this breaks
on Solaris and FreeBSD. At least.
2005-04-08 08:48:17 +00:00
Marty Kuhrt
9afaa51e3f updated instructions 2005-04-08 05:07:04 +00:00
Marty Kuhrt
c736a719f1 fixed control_y trap problem 2005-04-08 05:06:31 +00:00
Marty Kuhrt
37a547842b cast the call to Curl_inet_ntop for DECC compiler squawk 2005-04-08 05:01:40 +00:00
Daniel Stenberg
b9f1d43921 Unfortunately, if a ca file name is set the function fails for whatever reason
(missing file, bad file, etc), gnutls will no longer handshake properly but it
just loops forever. Therefore, we must return error if we get an error when
setting the CA cert file name. This is not the same behaviour as with OpenSSL.

Question/report posted to the help-gnutls mailing list, April 8 2005.
2005-04-07 22:47:43 +00:00
Daniel Stenberg
bec6423c02 one down 2005-04-07 22:14:22 +00:00
Daniel Stenberg
241b2b4ae3 set LD_LIBRARY_PATH when GnuTLS has been found 2005-04-07 22:13:40 +00:00
Daniel Stenberg
14d9b56937 cut 'n paste error 2005-04-07 21:12:09 +00:00
Daniel Stenberg
1c3766eb46 GnuTLS updates 2005-04-07 21:10:31 +00:00
Daniel Stenberg
70024d61eb GnuTLS! 2005-04-07 21:05:45 +00:00
Daniel Stenberg
2085f133d6 added new files 2005-04-07 20:56:04 +00:00
Daniel Stenberg
2a045dfceb fixed to build after the GnuTLS fixes 2005-04-07 20:36:48 +00:00
Daniel Stenberg
893cbaaf2f added some blurb about the GnuTLS license 2005-04-07 15:28:56 +00:00
Daniel Stenberg
6e61939382 GnuTLS support added. There's now a "generic" SSL layer that we use all over
internally, with code provided by sslgen.c. All SSL-layer-specific code is
then written in ssluse.c (for OpenSSL) and gtls.c (for GnuTLS).

As far as possible, internals should not need to know what SSL layer that is
in use. Building with GnuTLS currently makes two test cases fail.

TODO.gnutls contains a few known outstanding issues for the GnuTLS support.

GnuTLS support is enabled with configure --with-gnutls
2005-04-07 15:27:13 +00:00
Daniel Stenberg
015a618172 ssl_version_num is not used anymore 2005-04-07 15:21:50 +00:00
Daniel Stenberg
2a8b91cdb9 ssl_version_num won't be used anymore since we will soon offer multiple SSL
layers and it won't make sense to provide a numerical version for it. I also
doubt that many people have used this for anything critical.
2005-04-07 15:18:51 +00:00
Daniel Stenberg
bebd5dbc5a Add support for --with-gnutls. If configure detects OpenSSL, you need to
to explicitly disable that first with --without-ssl. Initial attempt.
2005-04-07 15:12:03 +00:00
Daniel Stenberg
018dbfe058 bail out if perl is missing, it is needed for building curl anyway 2005-04-07 14:26:03 +00:00
Daniel Stenberg
c6ea597817 check for libtoolize and aclocal to doublecheck the installations better 2005-04-07 08:59:39 +00:00
Daniel Stenberg
175b00c0a2 Try harder to see if arpa/nameser_compat.h REALLY is a good header file to
include, as it seems at least some AIX versions don't really allow it to be
include at the same time as the original nameser.h.
2005-04-07 07:38:53 +00:00
Daniel Stenberg
5ebc6e305e add SSPI 2005-04-07 07:30:02 +00:00
Daniel Stenberg
993600761f Tupone Alfredo fixed includes of arpa/nameser_compat.h to build fine on Mac OS
X.
2005-04-06 22:27:42 +00:00
Daniel Stenberg
1d9fff80b7 better errno constant replacements, as mentioned by Gisle Vanem 2005-04-06 21:14:58 +00:00
Gisle Vanem
c712b84dd5 Include inet_net_pton.h for 'struct in6_addr'. Ideally this
should come from <ws2tcpip.h>, but Winsock 1.1 should
suffice.
2005-04-06 18:58:33 +00:00
Gisle Vanem
dcf8dd4b5e Moved inet_net_pton.h to HHEADERS. 2005-04-06 18:55:59 +00:00
Daniel Stenberg
ba26c3fb22 check for struct sizes and use those sizes if the NS_* defines are lacking
(IRIX 6.5.22 it seems)
2005-04-06 14:11:50 +00:00
Daniel Stenberg
41563607a8 moved the *_inet_pton protos to inet_net_pton.h instead 2005-04-06 14:02:37 +00:00
Daniel Stenberg
2d4dcfb740 made the ares_inet_net_pton() proto use size_t size, as the function in the
code uses that
2005-04-06 13:54:02 +00:00
Dan Fandrich
34854e70cf Removed extraneous comma 2005-04-06 00:39:48 +00:00
Daniel Stenberg
758d9fe852 too late hacking error 2005-04-05 21:14:59 +00:00
Daniel Stenberg
6a6c0e7a73 test time-conditioned FTP uploads 2005-04-05 21:07:27 +00:00
Daniel Stenberg
ee44eec3e1 Christophe Legry's fix to grok time-conditoned uploads 2005-04-05 20:59:12 +00:00
Daniel Stenberg
eccd0d8e37 with these changes, it builds on my win32 cross-compiler 2005-04-05 20:20:14 +00:00
Daniel Stenberg
983be0ec60 check for another arpa header 2005-04-05 20:19:55 +00:00
Daniel Stenberg
243a45d840 check for the arpa/* headers 2005-04-05 20:08:15 +00:00
Dominick Meglio
60ec804047 Provided implementations of inet_net_pton and inet_pton from BIND for systems that do not include these functions. These will be necessary for CIDR support and IPv6 support. 2005-04-05 18:26:55 +00:00
Daniel Stenberg
c53e9ccf4a 7.13.3 in progress 2005-04-05 15:11:51 +00:00
Daniel Stenberg
6e8e0418fc 5.11 How do I make libcurl not receive the whole HTTP response? 2005-04-05 14:38:38 +00:00
Daniel Stenberg
e9eb52305f two more actual FAQs 2005-04-05 14:36:37 +00:00
Daniel Stenberg
8501ae748c restart with a blank page again 2005-04-05 07:55:41 +00:00
117 changed files with 3545 additions and 891 deletions

18
CHANGES
View File

@@ -6,6 +6,24 @@
Changelog
Daniel (8 April 2005)
- Cory Nelson reported a problem with a HTTP server that responded with a 304
response containing an "illegal" Content-Length: header, which was not
properly ignored by libcurl. Now it is. Test case 249 verifies.
Daniel (7 April 2005)
- Added ability to build and run with GnuTLS as an alternative to OpenSSL for
the secure layer. configure --with-gnutls enables with. Note that the
previous OpenSSL check still has preference and if it first detects OpenSSL,
it will not check for GnuTLS. You may need to explictly diable OpenSSL with
--without-ssl.
This work has been sponsored by The Written Word.
Daniel (5 April 2005)
- Christophe Legry fixed the post-upload check for FTP to not complain if the
upload was skipped due to a time-condition as set with
CURLOPT_TIMECONDITION. I added test case 247 and 248 to verify.
Version 7.13.2 (5 April 2005)

View File

@@ -1,57 +1,31 @@
Curl and libcurl 7.13.2
Curl and libcurl 7.14.0
Public curl release number: 87
Releases counted from the very beginning: 114
Public curl release number: 88
Releases counted from the very beginning: 115
Available command line options: 106
Available curl_easy_setopt() options: 122
Number of public functions in libcurl: 46
Amount of public web site mirrors: 20
Amount of public web site mirrors: 21
Number of known libcurl bindings: 31
This release includes the following changes:
o Added --form-string
o libcurl can be built with SSPI support. curl_version_info() then returns
a new feature bit: CURL_VERSION_SSPI. configure --enable-sspi added
o Added --proxy-anyauth
o Added runtests.1 and testcurl.1 man pages
o GnuTLS support, use configure --with-gnutls. Work on this was sponsored
by The Written Word.
This release includes the following bugfixes:
o the MSVC libcurl Makefile was fixed
o libcurl on Windows crash if resolver was active when easy handle was killed
o HTTP POST with auth and an initial 100 response before the 401/407
o configure's SSL-detection for msys/mingw
o better connection keep-alive when POSTing with HTTP Digest
o FTP-SSL
o reading FTP server response in multiple reads
o picking one out of multiple proxy auth methods
o inet_ntoa_r() when built with uClibc
o the so name issue for the LDAP library dynamic load
o crash when using SOCKS4 proxy
o a debug printf() was removed
o CURLOPT_FILETIME when downloading FTP corrupted data
o FTP upload resume now works even if no file is present on the site
o SSL seeding no longer attempts to read the whole random file
o HTTP 304 response with Content-Length: header
o time-conditioned FTP uploads
Other curl-related news since the previous public release:
o the cURL project is now over 7 years old
o daily curl binary builds for Windows fresh from CVS:
http://cool.haxx.se/curl-daily/
o curl-tracker is a new mailinglist for "tracker" activities:
http://cool.haxx.se/mailman/listinfo/curl-tracker
o libcurl binding for Common Lisp: http://common-lisp.net/project/cl-curl/
o pycurl 7.13.1 http://pycurl.sf.net
o http://curl.tolix.org is a new Californian mirror
o http://curl.seekmeup.com/ is a new mirror in US Texas
o http://curl.mirroring.de/ is a new german curl mirror
o pycurl 7.13.2: http://pycurl.sf.net/
This release would not have looked like this without help, code, reports and
advice from friends like these:
Dan Fandrich, Ignacio Vazquez-Abrams, Randy McMurchy, Dominick Meglio,
Jean-Marc Ranger, Tor Arntsen, Nodak Sodak, David Houlder, Gisle Vanem,
Christopher R. Palmer, Gwenole Beauchesne, Augustus Saunders, Jesper Jensen,
Tom Moers, Andres Garcia, Hardeep Singh, Marcelo Juchem
Christophe Legry,Cory Nelson
Thanks! (and sorry if I forgot to mention someone)

View File

@@ -1,6 +1,6 @@
Issues not sorted in any particular order.
To get fixed in 7.13.3 (planned release: June 2005)
To get fixed in 7.14.1 (planned release: June 2005)
======================
58 - Fix KNOWN_BUGS #19: "FTP 3rd party transfers with the multi interface
@@ -10,7 +10,7 @@ To get fixed in 7.13.3 (planned release: June 2005)
Awaits OpenSSL support for this, no need to support this in libcurl before
there's an OpenSSL release that does it.
To get fixed in 7.14.0
To get fixed in 7.15.0
======================
55 - Add a function to the multi interface that gets file descriptors, as an
@@ -24,7 +24,7 @@ To get fixed in 7.14.0
internally use and assume the multi interface. The select()-loop should
use the new function from (55).
To get fixed in 7.15.0
To get fixed in 7.16.0
======================
57 - Add an interface to libcurl for getting and setting cookies from an easy

13
ares/AUTHORS Normal file
View File

@@ -0,0 +1,13 @@
c-ares is based on ares, and these are the people that have worked on it since
the fork was made:
Daniel Stenberg
Dominick Meglio
liren at vivisimo.com
James Bursa
Duncan Wilcox
Dirk Manske
Dan Fandrich
Gisle Vanem
Gunter Knauf
Henrik Stoerner

View File

@@ -1,5 +1,32 @@
Changelog for the c-ares project
* April 9
- Made sortlist support IPv6 (this can probably use some testing).
- Made sortlist support CIDR matching for IPv4.
* April 8
- Added preliminary IPv6 support to ares_gethostbyname. Currently, sortlist
does not work with IPv6. Also provided an implementation of bitncmp from
BIND for systems that do not supply this function. This will be used to add
IPv6 support to sortlist.
- Made ares_gethostbyaddr support IPv6 by specifying AF_INET6 as the family.
The function can lookup IPv6 addresses both from files (/etc/hosts) and
DNS lookups.
* April 7
- Tupone Alfredo fixed includes of arpa/nameser_compat.h to build fine on Mac
OS X.
* April 5
- Dominick Meglio: Provided implementations of inet_net_pton and inet_pton
from BIND for systems that do not include these functions.
* March 11, 2005
- Dominick Meglio added ares_parse_aaaa_reply.c and did various

View File

@@ -12,7 +12,7 @@ MSVCFILES = vc/adig/adig.dep vc/adig/adig.dsp vc/adig/adig.mak \
# adig and ahost are just sample programs and thus not mentioned with the
# regular sources and headers
EXTRA_DIST = CHANGES README.cares Makefile.inc adig.c ahost.c $(man_MANS) \
$(MSVCFILES)
$(MSVCFILES) AUTHORS
VER=-version-info 0:0:0

View File

@@ -4,9 +4,10 @@ ares_gethostbyaddr.c ares_send.c ares__read_line.c ares_gethostbyname.c \
ares_strerror.c ares_cancel.c ares_init.c ares_timeout.c ares_destroy.c \
ares_mkquery.c ares_version.c ares_expand_name.c ares_parse_a_reply.c \
windows_port.c ares_expand_string.c ares_parse_ptr_reply.c \
ares_parse_aaaa_reply.c
ares_parse_aaaa_reply.c inet_net_pton.c bitncmp.c
HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h nameser.h
HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h nameser.h \
inet_net_pton.h
MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \
ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3 \

View File

@@ -30,12 +30,15 @@
#include "ares.h"
#include "ares_private.h"
#include "inet_net_pton.h"
int ares__get_hostent(FILE *fp, struct hostent **host)
int ares__get_hostent(FILE *fp, int family, struct hostent **host)
{
char *line = NULL, *p, *q, *canonical, **alias;
int status, linesize, end_at_hostname, naliases;
struct in_addr addr;
struct in6_addr addr6;
int addrlen = sizeof(struct in_addr);
struct hostent *hostent = NULL;
while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
@@ -56,6 +59,17 @@ int ares__get_hostent(FILE *fp, struct hostent **host)
*p = 0;
addr.s_addr = inet_addr(line);
if (addr.s_addr == INADDR_NONE)
{
if (ares_inet_pton(AF_INET6, line, &addr6) > 0)
{
if (family != AF_INET6)
continue;
addrlen = sizeof(struct in6_addr);
}
else
continue;
}
else if (family != AF_INET)
continue;
/* Get the canonical hostname. */
@@ -100,7 +114,7 @@ int ares__get_hostent(FILE *fp, struct hostent **host)
hostent->h_addr_list = malloc(2 * sizeof(char *));
if (!hostent->h_addr_list)
break;
hostent->h_addr_list[0] = malloc(sizeof(struct in_addr));
hostent->h_addr_list[0] = malloc(addrlen);
if (!hostent->h_addr_list[0])
break;
hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
@@ -134,9 +148,12 @@ int ares__get_hostent(FILE *fp, struct hostent **host)
}
hostent->h_aliases[naliases] = NULL;
hostent->h_addrtype = AF_INET;
hostent->h_length = sizeof(struct in_addr);
memcpy(hostent->h_addr_list[0], &addr, sizeof(struct in_addr));
hostent->h_addrtype = family;
hostent->h_length = addrlen;
if (family == AF_INET)
memcpy(hostent->h_addr_list[0], &addr, addrlen);
else if (family == AF_INET6)
memcpy(hostent->h_addr_list[0], &addr6, addrlen);
hostent->h_addr_list[1] = NULL;
*host = hostent;
free(line);

View File

@@ -21,6 +21,9 @@
#else
#include <netinet/in.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>

View File

@@ -12,7 +12,6 @@
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#include "setup.h"
#include <sys/types.h>
@@ -23,6 +22,9 @@
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdio.h>
@@ -31,6 +33,7 @@
#include "ares.h"
#include "ares_private.h"
#include "inet_net_pton.h"
#ifdef WATT32
#undef WIN32
@@ -39,7 +42,8 @@
struct addr_query {
/* Arguments passed to ares_gethostbyaddr() */
ares_channel channel;
struct in_addr addr;
union ares_addr addr;
int family;
ares_host_callback callback;
void *arg;
@@ -51,14 +55,21 @@ static void addr_callback(void *arg, int status, unsigned char *abuf,
int alen);
static void end_aquery(struct addr_query *aquery, int status,
struct hostent *host);
static int file_lookup(struct in_addr *addr, struct hostent **host);
static int file_lookup(union ares_addr *addr, int family, struct hostent **host);
void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
int family, ares_host_callback callback, void *arg)
{
struct addr_query *aquery;
if (family != AF_INET || addrlen != sizeof(struct in_addr))
if (family != AF_INET && family != AF_INET6)
{
callback(arg, ARES_ENOTIMP, NULL);
return;
}
if ((family == AF_INET && addrlen != sizeof(struct in_addr)) ||
(family == AF_INET6 && addrlen != sizeof(struct in6_addr)))
{
callback(arg, ARES_ENOTIMP, NULL);
return;
@@ -71,7 +82,11 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
return;
}
aquery->channel = channel;
memcpy(&aquery->addr, addr, sizeof(aquery->addr));
if (family == AF_INET)
memcpy(&aquery->addr.addr4, addr, sizeof(struct in_addr));
else
memcpy(&aquery->addr.addr6, addr, sizeof(struct in6_addr));
aquery->family = family;
aquery->callback = callback;
aquery->arg = arg;
aquery->remaining_lookups = channel->lookups;
@@ -82,7 +97,7 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
static void next_lookup(struct addr_query *aquery)
{
const char *p;
char name[64];
char name[128];
int a1, a2, a3, a4, status;
struct hostent *host;
unsigned long addr;
@@ -92,18 +107,38 @@ static void next_lookup(struct addr_query *aquery)
switch (*p)
{
case 'b':
addr = ntohl(aquery->addr.s_addr);
a1 = (int)((addr >> 24) & 0xff);
a2 = (int)((addr >> 16) & 0xff);
a3 = (int)((addr >> 8) & 0xff);
a4 = (int)(addr & 0xff);
sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1);
aquery->remaining_lookups = p + 1;
ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,
aquery);
if (aquery->family == AF_INET)
{
addr = ntohl(aquery->addr.addr4.s_addr);
a1 = (int)((addr >> 24) & 0xff);
a2 = (int)((addr >> 16) & 0xff);
a3 = (int)((addr >> 8) & 0xff);
a4 = (int)(addr & 0xff);
sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1);
aquery->remaining_lookups = p + 1;
ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,
aquery);
}
else
{
unsigned char *bytes;
bytes = (unsigned char *)&aquery->addr.addr6.s6_addr;
sprintf(name, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa",
bytes[15]&0xf, bytes[15] >> 4, bytes[14]&0xf, bytes[14] >> 4,
bytes[13]&0xf, bytes[13] >> 4, bytes[12]&0xf, bytes[12] >> 4,
bytes[11]&0xf, bytes[11] >> 4, bytes[10]&0xf, bytes[10] >> 4,
bytes[9]&0xf, bytes[9] >> 4, bytes[8]&0xf, bytes[8] >> 4,
bytes[7]&0xf, bytes[7] >> 4, bytes[6]&0xf, bytes[6] >> 4,
bytes[5]&0xf, bytes[5] >> 4, bytes[4]&0xf, bytes[4] >> 4,
bytes[3]&0xf, bytes[3] >> 4, bytes[2]&0xf, bytes[2] >> 4,
bytes[1]&0xf, bytes[1] >> 4, bytes[0]&0xf, bytes[0] >> 4);
aquery->remaining_lookups = p + 1;
ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,
aquery);
}
return;
case 'f':
status = file_lookup(&aquery->addr, &host);
status = file_lookup(&aquery->addr, aquery->family, &host);
if (status != ARES_ENOTFOUND)
{
end_aquery(aquery, status, host);
@@ -122,8 +157,12 @@ static void addr_callback(void *arg, int status, unsigned char *abuf, int alen)
if (status == ARES_SUCCESS)
{
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr,
sizeof(struct in_addr), AF_INET, &host);
if (aquery->family == AF_INET)
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr4,
sizeof(struct in_addr), AF_INET, &host);
else
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr6,
sizeof(struct in6_addr), AF_INET6, &host);
end_aquery(aquery, status, host);
}
else if (status == ARES_EDESTRUCTION)
@@ -141,7 +180,7 @@ static void end_aquery(struct addr_query *aquery, int status,
free(aquery);
}
static int file_lookup(struct in_addr *addr, struct hostent **host)
static int file_lookup(union ares_addr *addr, int family, struct hostent **host)
{
FILE *fp;
int status;
@@ -178,11 +217,23 @@ static int file_lookup(struct in_addr *addr, struct hostent **host)
fp = fopen(PATH_HOSTS, "r");
if (!fp)
return ARES_ENOTFOUND;
while ((status = ares__get_hostent(fp, host)) == ARES_SUCCESS)
while ((status = ares__get_hostent(fp, family, host)) == ARES_SUCCESS)
{
if (memcmp((*host)->h_addr, addr, sizeof(struct in_addr)) == 0)
break;
if (family != (*host)->h_addrtype)
{
ares_free_hostent(*host);
continue;
}
if (family == AF_INET)
{
if (memcmp((*host)->h_addr, &addr->addr4, sizeof(struct in_addr)) == 0)
break;
}
else if (family == AF_INET6)
{
if (memcmp((*host)->h_addr, &addr->addr6, sizeof(struct in6_addr)) == 0)
break;
}
ares_free_hostent(*host);
}
fclose(fp);

View File

@@ -33,6 +33,8 @@
#include "ares.h"
#include "ares_private.h"
#include "inet_net_pton.h"
#include "bitncmp.h"
#ifdef WATT32
#undef WIN32
@@ -44,7 +46,7 @@ struct host_query {
char *name;
ares_host_callback callback;
void *arg;
int family;
const char *remaining_lookups;
};
@@ -53,13 +55,17 @@ static void host_callback(void *arg, int status, unsigned char *abuf,
int alen);
static void end_hquery(struct host_query *hquery, int status,
struct hostent *host);
static int fake_hostent(const char *name, ares_host_callback callback,
static int fake_hostent(const char *name, int family, ares_host_callback callback,
void *arg);
static int file_lookup(const char *name, struct hostent **host);
static int file_lookup(const char *name, int family, struct hostent **host);
static void sort_addresses(struct hostent *host, struct apattern *sortlist,
int nsort);
static void sort6_addresses(struct hostent *host, struct apattern *sortlist,
int nsort);
static int get_address_index(struct in_addr *addr, struct apattern *sortlist,
int nsort);
static int get6_address_index(struct in6_addr *addr, struct apattern *sortlist,
int nsort);
void ares_gethostbyname(ares_channel channel, const char *name, int family,
ares_host_callback callback, void *arg)
@@ -67,13 +73,13 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
struct host_query *hquery;
/* Right now we only know how to look up Internet addresses. */
if (family != AF_INET)
if (family != AF_INET && family != AF_INET6)
{
callback(arg, ARES_ENOTIMP, NULL);
return;
}
if (fake_hostent(name, callback, arg))
if (fake_hostent(name, family, callback, arg))
return;
/* Allocate and fill in the host query structure. */
@@ -85,6 +91,7 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
}
hquery->channel = channel;
hquery->name = strdup(name);
hquery->family = family;
if (!hquery->name)
{
free(hquery);
@@ -112,13 +119,17 @@ static void next_lookup(struct host_query *hquery)
case 'b':
/* DNS lookup */
hquery->remaining_lookups = p + 1;
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
hquery);
if (hquery->family == AF_INET6)
ares_search(hquery->channel, hquery->name, C_IN, T_AAAA, host_callback,
hquery);
else
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
hquery);
return;
case 'f':
/* Host file lookup */
status = file_lookup(hquery->name, &host);
status = file_lookup(hquery->name, hquery->family, &host);
if (status != ARES_ENOTFOUND)
{
end_hquery(hquery, status, host);
@@ -138,11 +149,27 @@ static void host_callback(void *arg, int status, unsigned char *abuf, int alen)
if (status == ARES_SUCCESS)
{
status = ares_parse_a_reply(abuf, alen, &host);
if (host && channel->nsort)
sort_addresses(host, channel->sortlist, channel->nsort);
if (hquery->family == AF_INET)
{
status = ares_parse_a_reply(abuf, alen, &host);
if (host && channel->nsort)
sort_addresses(host, channel->sortlist, channel->nsort);
}
else if (hquery->family == AF_INET6)
{
status = ares_parse_aaaa_reply(abuf, alen, &host);
if (host && channel->nsort)
sort6_addresses(host, channel->sortlist, channel->nsort);
}
end_hquery(hquery, status, host);
}
else if (status == ARES_ENODATA && hquery->family == AF_INET6)
{
/* There was no AAAA now lookup an A */
hquery->family = AF_INET;
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
hquery);
}
else if (status == ARES_EDESTRUCTION)
end_hquery(hquery, status, NULL);
else
@@ -162,36 +189,34 @@ static void end_hquery(struct host_query *hquery, int status,
/* If the name looks like an IP address, fake up a host entry, end the
* query immediately, and return true. Otherwise return false.
*/
static int fake_hostent(const char *name, ares_host_callback callback,
static int fake_hostent(const char *name, int family, ares_host_callback callback,
void *arg)
{
struct in_addr addr;
struct hostent hostent;
const char *p;
char *aliases[1] = { NULL };
char *addrs[2];
int result = 0;
struct in_addr in;
struct in6_addr in6;
/* It only looks like an IP address if it's all numbers and dots. */
for (p = name; *p; p++)
{
if (!isdigit((unsigned char)*p) && *p != '.')
return 0;
}
if (family == AF_INET)
result = ((in.s_addr = inet_addr(name)) == INADDR_NONE ? 0 : 1);
else if (family == AF_INET6)
result = (ares_inet_pton(AF_INET6, name, &in6) < 1 ? 0 : 1);
/* It also only looks like an IP address if it's non-zero-length and
* doesn't end with a dot.
*/
if (p == name || *(p - 1) == '.')
if (!result)
return 0;
/* It looks like an IP address. Figure out what IP address it is. */
addr.s_addr = inet_addr(name);
if (addr.s_addr == INADDR_NONE)
if (family == AF_INET)
{
callback(arg, ARES_EBADNAME, NULL);
return 1;
hostent.h_length = sizeof(struct in_addr);
addrs[0] = (char *)&in;
}
else if (family == AF_INET6)
{
hostent.h_length = sizeof(struct in6_addr);
addrs[0] = (char *)&in6;
}
/* Duplicate the name, to avoid a constness violation. */
hostent.h_name = strdup(name);
if (!hostent.h_name)
@@ -201,11 +226,9 @@ static int fake_hostent(const char *name, ares_host_callback callback,
}
/* Fill in the rest of the host structure and terminate the query. */
addrs[0] = (char *) &addr;
addrs[1] = NULL;
hostent.h_aliases = aliases;
hostent.h_addrtype = AF_INET;
hostent.h_length = sizeof(struct in_addr);
hostent.h_addrtype = family;
hostent.h_addr_list = addrs;
callback(arg, ARES_SUCCESS, &hostent);
@@ -213,7 +236,7 @@ static int fake_hostent(const char *name, ares_host_callback callback,
return 1;
}
static int file_lookup(const char *name, struct hostent **host)
static int file_lookup(const char *name, int family, struct hostent **host)
{
FILE *fp;
char **alias;
@@ -252,7 +275,7 @@ static int file_lookup(const char *name, struct hostent **host)
if (!fp)
return ARES_ENOTFOUND;
while ((status = ares__get_hostent(fp, host)) == ARES_SUCCESS)
while ((status = ares__get_hostent(fp, family, host)) == ARES_SUCCESS)
{
if (strcasecmp((*host)->h_name, name) == 0)
break;
@@ -310,8 +333,66 @@ static int get_address_index(struct in_addr *addr, struct apattern *sortlist,
for (i = 0; i < nsort; i++)
{
if ((addr->s_addr & sortlist[i].mask.s_addr) == sortlist[i].addr.s_addr)
break;
if (sortlist[i].family != AF_INET)
continue;
if (sortlist[i].type == PATTERN_MASK)
{
if ((addr->s_addr & sortlist[i].mask.addr.addr4.s_addr)
== sortlist[i].addr.addr4.s_addr)
break;
}
else
{
if (!ares_bitncmp(&addr->s_addr, &sortlist[i].addr.addr4.s_addr,
sortlist[i].mask.bits))
break;
}
}
return i;
}
static void sort6_addresses(struct hostent *host, struct apattern *sortlist,
int nsort)
{
struct in6_addr a1, a2;
int i1, i2, ind1, ind2;
/* This is a simple insertion sort, not optimized at all. i1 walks
* through the address list, with the loop invariant that everything
* to the left of i1 is sorted. In the loop body, the value at i1 is moved
* back through the list (via i2) until it is in sorted order.
*/
for (i1 = 0; host->h_addr_list[i1]; i1++)
{
memcpy(&a1, host->h_addr_list[i1], sizeof(struct in6_addr));
ind1 = get6_address_index(&a1, sortlist, nsort);
for (i2 = i1 - 1; i2 >= 0; i2--)
{
memcpy(&a2, host->h_addr_list[i2], sizeof(struct in6_addr));
ind2 = get6_address_index(&a2, sortlist, nsort);
if (ind2 <= ind1)
break;
memcpy(host->h_addr_list[i2 + 1], &a2, sizeof(struct in6_addr));
}
memcpy(host->h_addr_list[i2 + 1], &a1, sizeof(struct in6_addr));
}
}
/* Find the first entry in sortlist which matches addr. Return nsort
* if none of them match.
*/
static int get6_address_index(struct in6_addr *addr, struct apattern *sortlist,
int nsort)
{
int i;
for (i = 0; i < nsort; i++)
{
if (sortlist[i].family != AF_INET6)
continue;
if (!ares_bitncmp(&addr->s6_addr, &sortlist[i].addr.addr6.s6_addr, sortlist[i].mask.bits))
break;
}
return i;
}

View File

@@ -27,10 +27,17 @@
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -44,6 +51,7 @@
#include <errno.h>
#include "ares.h"
#include "ares_private.h"
#include "inet_net_pton.h"
#ifdef WATT32
#undef WIN32 /* Redefined in MingW/MSVC headers */
@@ -61,6 +69,7 @@ static int set_search(ares_channel channel, const char *str);
static int set_options(ares_channel channel, const char *str);
static const char *try_option(const char *p, const char *q, const char *opt);
#ifndef WIN32
static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat);
static int ip_addr(const char *s, int len, struct in_addr *addr);
static void natural_mask(struct apattern *pat);
static int config_domain(ares_channel channel, char *str);
@@ -821,36 +830,69 @@ static int config_nameserver(struct server_state **servers, int *nservers,
static int config_sortlist(struct apattern **sortlist, int *nsort,
const char *str)
{
struct apattern pat, *newsort;
struct apattern pat;
const char *q;
/* Add sortlist entries. */
while (*str && *str != ';')
{
int bits;
char ipbuf[16], ipbufpfx[32];
/* Find just the IP */
q = str;
while (*q && *q != '/' && *q != ';' && !isspace((unsigned char)*q))
q++;
if (ip_addr(str, (int)(q - str), &pat.addr) == 0)
memcpy(ipbuf, str, (int)(q-str));
ipbuf[(int)(q-str)] = 0;
/* Find the prefix */
if (*q == '/')
{
/* We have a pattern address; now determine the mask. */
if (*q == '/')
const char *str2 = q+1;
while (*q && *q != ';' && !isspace((unsigned char)*q))
q++;
memcpy(ipbufpfx, str, (int)(q-str));
ipbufpfx[(int)(q-str)] = 0;
str = str2;
}
else
ipbufpfx[0] = 0;
/* Lets see if it is CIDR */
/* First we'll try IPv6 */
if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx ? ipbufpfx : ipbuf, &pat.addr.addr6,
sizeof(pat.addr.addr6))) > 0)
{
pat.type = PATTERN_CIDR;
pat.mask.bits = bits;
pat.family = AF_INET6;
if (!sortlist_alloc(sortlist, nsort, &pat))
return ARES_ENOMEM;
}
if (ipbufpfx &&
(bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addr.addr4,
sizeof(pat.addr.addr4))) > 0)
{
pat.type = PATTERN_CIDR;
pat.mask.bits = bits;
pat.family = AF_INET;
if (!sortlist_alloc(sortlist, nsort, &pat))
return ARES_ENOMEM;
}
/* See if it is just a regular IP */
else if (ip_addr(ipbuf, (int)(q-str), &pat.addr.addr4) == 0)
{
if (ipbufpfx)
{
str = q + 1;
while (*q && *q != ';' && !isspace((unsigned char)*q))
q++;
if (ip_addr(str, (int)(q - str), &pat.mask) != 0)
memcpy(ipbuf, str, (int)(q-str));
ipbuf[(int)(q-str)] = 0;
if (ip_addr(ipbuf, (int)(q - str), &pat.mask.addr.addr4) != 0)
natural_mask(&pat);
}
else
natural_mask(&pat);
/* Add this pattern to our list. */
newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
if (!newsort)
pat.family = AF_INET;
pat.type = PATTERN_MASK;
if (!sortlist_alloc(sortlist, nsort, &pat))
return ARES_ENOMEM;
newsort[*nsort] = pat;
*sortlist = newsort;
(*nsort)++;
}
else
{
@@ -968,16 +1010,25 @@ static const char *try_option(const char *p, const char *q, const char *opt)
return ((size_t)(q - p) > len && !strncmp(p, opt, len)) ? &p[len] : NULL;
}
#ifndef WIN32
static int ip_addr(const char *s, int len, struct in_addr *addr)
static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat)
{
struct apattern *newsort;
newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern));
if (!newsort)
return 0;
newsort[*nsort] = *pat;
*sortlist = newsort;
(*nsort)++;
return 1;
}
#ifndef WIN32
static int ip_addr(const char *ipbuf, int len, struct in_addr *addr)
{
char ipbuf[16];
/* Four octets and three periods yields at most 15 characters. */
if (len > 15)
return -1;
memcpy(ipbuf, s, len);
ipbuf[len] = 0;
addr->s_addr = inet_addr(ipbuf);
if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0)
@@ -992,16 +1043,16 @@ static void natural_mask(struct apattern *pat)
/* Store a host-byte-order copy of pat in a struct in_addr. Icky,
* but portable.
*/
addr.s_addr = ntohl(pat->addr.s_addr);
addr.s_addr = ntohl(pat->addr.addr4.s_addr);
/* This is out of date in the CIDR world, but some people might
* still rely on it.
*/
if (IN_CLASSA(addr.s_addr))
pat->mask.s_addr = htonl(IN_CLASSA_NET);
pat->mask.addr.addr4.s_addr = htonl(IN_CLASSA_NET);
else if (IN_CLASSB(addr.s_addr))
pat->mask.s_addr = htonl(IN_CLASSB_NET);
pat->mask.addr.addr4.s_addr = htonl(IN_CLASSB_NET);
else
pat->mask.s_addr = htonl(IN_CLASSC_NET);
pat->mask.addr.addr4.s_addr = htonl(IN_CLASSC_NET);
}
#endif

43
ares/ares_ipv6.h Normal file
View File

@@ -0,0 +1,43 @@
/* $Id$ */
/*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#ifndef ARES_IPV6_H
#define ARES_IPV6_H
#ifndef HAVE_PF_INET6
#define PF_INET6 AF_INET6
#endif
#ifndef HAVE_STRUCT_IN6_ADDR
struct in6_addr
{
unsigned char s6_addr[16];
};
#endif
#ifndef NS_IN6ADDRSZ
#define NS_IN6ADDRSZ SIZEOF_STRUCT_IN6_ADDR
#endif
#ifndef NS_INADDRSZ
#define NS_INADDRSZ SIZEOF_STRUCT_IN_ADDR
#endif
#ifndef NS_INT16SZ
#define NS_INT16SZ 2
#endif
#endif /* ARES_IPV6_H */

View File

@@ -21,6 +21,9 @@
#else
#include <netinet/in.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>

View File

@@ -24,6 +24,9 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>

View File

@@ -30,6 +30,7 @@
#include <string.h>
#include "ares.h"
#include "ares_dns.h"
#include "inet_net_pton.h"
#include "ares_private.h"
int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,

View File

@@ -23,6 +23,9 @@
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>

View File

@@ -69,6 +69,8 @@
#endif
#include "ares_ipv6.h"
struct send_request {
/* Remaining data to send */
const unsigned char *data;
@@ -124,9 +126,23 @@ struct query {
};
/* An IP address pattern; matches an IP address X if X & mask == addr */
#define PATTERN_MASK 0x1
#define PATTERN_CIDR 0x2
union ares_addr {
struct in_addr addr4;
struct in6_addr addr6;
};
struct apattern {
struct in_addr addr;
struct in_addr mask;
union ares_addr addr;
union
{
union ares_addr addr;
unsigned short bits;
} mask;
int family;
unsigned short type;
};
struct ares_channeldata {
@@ -156,7 +172,7 @@ struct ares_channeldata {
void ares__send_query(ares_channel channel, struct query *query, time_t now);
void ares__close_sockets(struct server_state *server);
int ares__get_hostent(FILE *fp, struct hostent **host);
int ares__get_hostent(FILE *fp, int family, struct hostent **host);
int ares__read_line(FILE *fp, char **buf, int *bufsize);
#ifdef CURLDEBUG

View File

@@ -27,6 +27,9 @@
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

View File

@@ -21,6 +21,9 @@
#else
#include <netinet/in.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>

View File

@@ -21,6 +21,9 @@
#else
#include <netinet/in.h>
#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif
#endif
#include <stdlib.h>

60
ares/bitncmp.c Normal file
View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HAVE_BITNCMP
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include "bitncmp.h"
/*
* int
* bitncmp(l, r, n)
* compare bit masks l and r, for n bits.
* return:
* -1, 1, or 0 in the libc tradition.
* note:
* network byte order assumed. this means 192.5.5.240/28 has
* 0x11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), June 1996
*/
int
ares_bitncmp(const void *l, const void *r, int n) {
unsigned int lb, rb;
int x, b;
b = n / 8;
x = memcmp(l, r, b);
if (x)
return (x);
lb = ((const unsigned char *)l)[b];
rb = ((const unsigned char *)r)[b];
for (b = n % 8; b > 0; b--) {
if ((lb & 0x80) != (rb & 0x80)) {
if (lb & 0x80)
return (1);
return (-1);
}
lb <<= 1;
rb <<= 1;
}
return (0);
}
#endif

26
ares/bitncmp.h Normal file
View File

@@ -0,0 +1,26 @@
/* $Id$ */
/*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#ifndef BITNCMP_H
#define BITNCMP_H
#ifndef HAVE_BITNCMP
int ares_bitncmp(const void *l, const void *r, int n);
#else
#define ares_bitncmp(x,y,z) bitncmp(x,y,z)
#endif
#endif /* BITNCMP_H */

View File

@@ -1,7 +1,7 @@
#!/bin/sh
libtoolize --copy --automake --force
aclocal
autoheader
autoconf
automake --add-missing
${LIBTOOLIZE:-libtoolize} --copy --automake --force
${ACLOCAL:-aclocal}
${AUTOHEADER:-autoheader}
${AUTOCONF:-autoconf}
${AUTOMAKE:-automake} --add-missing

View File

@@ -67,6 +67,20 @@ AC_CHECK_HEADERS(
sys/socket.h \
winsock.h \
netinet/in.h \
arpa/nameser.h \
arpa/nameser_compat.h \
arpa/inet.h, , ,
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
dnl We do this default-include simply to make sure that the nameser_compat.h
dnl header *REALLY* can be include after the new nameser.h. It seems AIX 5.1
dnl (and others?) is not designed to allow this.
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
]
)
dnl check for AF_INET6
@@ -120,4 +134,105 @@ CARES_CHECK_STRUCT(
AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.])
)
dnl check for inet_pton
AC_CHECK_FUNCS(inet_pton)
dnl Some systems have it, but not IPv6
if test "$ac_cv_func_inet_pton" = "yes" ; then
AC_MSG_CHECKING(if inet_pton supports IPv6)
AC_TRY_RUN(
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
int main()
{
struct in6_addr addr6;
if (inet_pton(AF_INET6, "::1", &addr6) < 1)
exit(1);
else
exit(0);
}
], [
AC_MSG_RESULT(yes)
AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6,1,[Define to 1 if inet_pton supports IPv6.])
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
fi
dnl Check for inet_net_pton
AC_CHECK_FUNCS(inet_net_pton)
dnl Again, some systems have it, but not IPv6
if test "$ac_cv_func_inet_net_pton" = "yes" ; then
AC_MSG_CHECKING(if inet_net_pton supports IPv6)
AC_TRY_RUN(
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
int main()
{
struct in6_addr addr6;
if (inet_net_pton(AF_INET6, "::1", &addr6, sizeof(addr6)) < 1)
exit(1);
else
exit(0);
}
], [
AC_MSG_RESULT(yes)
AC_DEFINE_UNQUOTED(HAVE_INET_NET_PTON_IPV6,1,[Define to 1 if inet_net_pton supports IPv6.])
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
fi
AC_CHECK_SIZEOF(struct in6_addr, ,
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
]
)
AC_CHECK_SIZEOF(struct in_addr, ,
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
]
)
AC_CHECK_FUNCS(bitncmp)
AC_OUTPUT(Makefile)

433
ares/inet_net_pton.c Normal file
View File

@@ -0,0 +1,433 @@
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "setup.h"
#include <sys/types.h>
#if defined(WIN32) && !defined(WATT32)
#include "nameser.h"
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#endif
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ares_ipv6.h"
#include "inet_net_pton.h"
#if !defined(HAVE_INET_NET_PTON) || !defined(HAVE_INET_NET_PTON_IPV6) || \
!defined(HAVE_INET_PTON) || !defined(HAVE_INET_PTON_IPV6)
/*
* static int
* inet_net_pton_ipv4(src, dst, size)
* convert IPv4 network number from presentation to network format.
* accepts hex octets, hex strings, decimal octets, and /CIDR.
* "size" is in bytes and describes "dst".
* return:
* number of bits, either imputed classfully or specified with /CIDR,
* or -1 if some failure occurred (check errno). ENOENT means it was
* not an IPv4 network specification.
* note:
* network byte order assumed. this means 192.5.5.240/28 has
* 0b11110000 in its fourth octet.
* author:
* Paul Vixie (ISC), June 1996
*/
static int
inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size) {
static const char xdigits[] = "0123456789abcdef";
static const char digits[] = "0123456789";
int n, ch, tmp = 0, dirty, bits;
const unsigned char *odst = dst;
ch = *src++;
if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
&& isascii((unsigned char)(src[1]))
&& isxdigit((unsigned char)(src[1]))) {
/* Hexadecimal: Eat nybble string. */
if (size <= 0U)
goto emsgsize;
dirty = 0;
src++; /* skip x or X. */
while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
if (isupper(ch))
ch = tolower(ch);
n = strchr(xdigits, ch) - xdigits;
if (dirty == 0)
tmp = n;
else
tmp = (tmp << 4) | n;
if (++dirty == 2) {
if (size-- <= 0U)
goto emsgsize;
*dst++ = (unsigned char) tmp;
dirty = 0;
}
}
if (dirty) { /* Odd trailing nybble? */
if (size-- <= 0U)
goto emsgsize;
*dst++ = (unsigned char) (tmp << 4);
}
} else if (isascii(ch) && isdigit(ch)) {
/* Decimal: eat dotted digit string. */
for (;;) {
tmp = 0;
do {
n = strchr(digits, ch) - digits;
tmp *= 10;
tmp += n;
if (tmp > 255)
goto enoent;
} while ((ch = *src++) != '\0' &&
isascii(ch) && isdigit(ch));
if (size-- <= 0U)
goto emsgsize;
*dst++ = (unsigned char) tmp;
if (ch == '\0' || ch == '/')
break;
if (ch != '.')
goto enoent;
ch = *src++;
if (!isascii(ch) || !isdigit(ch))
goto enoent;
}
} else
goto enoent;
bits = -1;
if (ch == '/' && isascii((unsigned char)(src[0])) &&
isdigit((unsigned char)(src[0])) && dst > odst) {
/* CIDR width specifier. Nothing can follow it. */
ch = *src++; /* Skip over the /. */
bits = 0;
do {
n = strchr(digits, ch) - digits;
bits *= 10;
bits += n;
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
if (bits > 32)
goto emsgsize;
}
/* Firey death and destruction unless we prefetched EOS. */
if (ch != '\0')
goto enoent;
/* If nothing was written to the destination, we found no address. */
if (dst == odst)
goto enoent;
/* If no CIDR spec was given, infer width from net class. */
if (bits == -1) {
if (*odst >= 240) /* Class E */
bits = 32;
else if (*odst >= 224) /* Class D */
bits = 8;
else if (*odst >= 192) /* Class C */
bits = 24;
else if (*odst >= 128) /* Class B */
bits = 16;
else /* Class A */
bits = 8;
/* If imputed mask is narrower than specified octets, widen. */
if (bits < ((dst - odst) * 8))
bits = (dst - odst) * 8;
/*
* If there are no additional bits specified for a class D
* address adjust bits to 4.
*/
if (bits == 8 && *odst == 224)
bits = 4;
}
/* Extend network to cover the actual mask. */
while (bits > ((dst - odst) * 8)) {
if (size-- <= 0U)
goto emsgsize;
*dst++ = '\0';
}
return (bits);
enoent:
errno = ENOENT;
return (-1);
emsgsize:
errno = EMSGSIZE;
return (-1);
}
static int
getbits(const char *src, int *bitsp) {
static const char digits[] = "0123456789";
int n;
int val;
char ch;
val = 0;
n = 0;
while ((ch = *src++) != '\0') {
const char *pch;
pch = strchr(digits, ch);
if (pch != NULL) {
if (n++ != 0 && val == 0) /* no leading zeros */
return (0);
val *= 10;
val += (pch - digits);
if (val > 128) /* range */
return (0);
continue;
}
return (0);
}
if (n == 0)
return (0);
*bitsp = val;
return (1);
}
static int
getv4(const char *src, unsigned char *dst, int *bitsp) {
static const char digits[] = "0123456789";
unsigned char *odst = dst;
int n;
unsigned int val;
char ch;
val = 0;
n = 0;
while ((ch = *src++) != '\0') {
const char *pch;
pch = strchr(digits, ch);
if (pch != NULL) {
if (n++ != 0 && val == 0) /* no leading zeros */
return (0);
val *= 10;
val += (pch - digits);
if (val > 255) /* range */
return (0);
continue;
}
if (ch == '.' || ch == '/') {
if (dst - odst > 3) /* too many octets? */
return (0);
*dst++ = val;
if (ch == '/')
return (getbits(src, bitsp));
val = 0;
n = 0;
continue;
}
return (0);
}
if (n == 0)
return (0);
if (dst - odst > 3) /* too many octets? */
return (0);
*dst++ = val;
return (1);
}
static int
inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) {
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned int val;
int digits;
int bits;
size_t bytes;
int words;
int ipv4;
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
goto enoent;
curtok = src;
saw_xdigit = 0;
val = 0;
digits = 0;
bits = -1;
ipv4 = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (++digits > 4)
goto enoent;
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
goto enoent;
colonp = tp;
continue;
} else if (*src == '\0')
goto enoent;
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
saw_xdigit = 0;
digits = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
getv4(curtok, tp, &bits) > 0) {
tp += NS_INADDRSZ;
saw_xdigit = 0;
ipv4 = 1;
break; /* '\0' was seen by inet_pton4(). */
}
if (ch == '/' && getbits(src, &bits) > 0)
break;
goto enoent;
}
if (saw_xdigit) {
if (tp + NS_INT16SZ > endp)
goto enoent;
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
}
if (bits == -1)
bits = 128;
words = (bits + 15) / 16;
if (words < 2)
words = 2;
if (ipv4)
words = 8;
endp = tmp + 2 * words;
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
if (tp == endp)
goto enoent;
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
goto enoent;
bytes = (bits + 7) / 8;
if (bytes > size)
goto emsgsize;
memcpy(dst, tmp, bytes);
return (bits);
enoent:
errno = ENOENT;
return (-1);
emsgsize:
errno = EMSGSIZE;
return (-1);
}
/*
* int
* inet_net_pton(af, src, dst, size)
* convert network number from presentation to network format.
* accepts hex octets, hex strings, decimal octets, and /CIDR.
* "size" is in bytes and describes "dst".
* return:
* number of bits, either imputed classfully or specified with /CIDR,
* or -1 if some failure occurred (check errno). ENOENT means it was
* not a valid network specification.
* author:
* Paul Vixie (ISC), June 1996
*/
int
ares_inet_net_pton(int af, const char *src, void *dst, size_t size) {
switch (af) {
case AF_INET:
return (inet_net_pton_ipv4(src, dst, size));
case AF_INET6:
return (inet_net_pton_ipv6(src, dst, size));
default:
errno = EAFNOSUPPORT;
return (-1);
}
}
#endif
#if !defined(HAVE_INET_PTON) || !defined(HAVE_INET_PTON_IPV6)
int ares_inet_pton(int af, const char *src, void *dst) {
int size, result;
if (af == AF_INET)
size = sizeof(struct in_addr);
else if (af == AF_INET6)
size = sizeof(struct in6_addr);
else
{
errno = EAFNOSUPPORT;
return -1;
}
result = ares_inet_net_pton(af, src, dst, size);
if (result == -1 && errno == ENOENT)
return 0;
return (result > -1 ? 1 : -1);
}
#endif

31
ares/inet_net_pton.h Normal file
View File

@@ -0,0 +1,31 @@
/* $Id$ */
/*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#ifndef INET_NET_PTON_H
#define INET_NET_PTON_H
#if defined(HAVE_INET_PTON) && defined(HAVE_INET_PTON_IPV6)
#define ares_inet_pton(x,y,z) inet_pton(x,y,z)
#else
int ares_inet_pton(int af, const char *src, void *dst);
#endif
#if defined(HAVE_INET_NET_PTON) && defined(HAVE_INET_NET_PTON_IPV6)
#define ares_inet_net_pton(w,x,y,z) inet_net_pton(w,x,y,z)
#else
int ares_inet_net_pton(int af, const char *src, void *dst, size_t size);
#endif
#endif /* INET_NET_PTON_H */

View File

@@ -16,6 +16,8 @@
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EMSGSIZE WSAEMSGSIZE
#define EAFNOSUPPORT WSAEAFNOSUPPORT
/* Structure for scatter/gather I/O. */
struct iovec
@@ -37,7 +39,9 @@ int ares_gettimeofday(struct timeval *tv, struct timezone *tz);
#endif /* !NETWARE */
#define NS_CMPRSFLGS 0xc0
#define NS_IN6ADDRSZ 16
#define NS_INT16SZ 2
#define NS_INADDRSZ 4
/* Flag bits indicating name compression. */
#define INDIR_MASK NS_CMPRSFLGS

View File

@@ -78,15 +78,4 @@ int ares_strcasecmp(const char *s1, const char *s2);
#endif
#endif
#ifndef HAVE_PF_INET6
#define PF_INET6 AF_INET6
#endif
#ifndef HAVE_STRUCT_IN6_ADDR
struct in6_addr
{
unsigned char s6_addr[16];
};
#endif
#endif /* ARES_SETUP_H */

View File

@@ -85,6 +85,14 @@ fi
echo "buildconf: automake version $am_version (ok)"
ac=`findtool aclocal`
if test -z "$ac"; then
echo "buildconf: aclocal not found. Weird automake installation!"
exit 1
else
echo "buildconf: aclocal found"
fi
#--------------------------------------------------------------------------
# libtool check
@@ -142,6 +150,13 @@ fi
echo "buildconf: libtool version $lt_version (ok)"
if test -f "$LIBTOOLIZE"; then
echo "buildconf: libtoolize found"
else
echo "buildconf: libtoolize not found. Weird libtool installation!"
exit 1
fi
#--------------------------------------------------------------------------
# m4 check
#
@@ -155,6 +170,10 @@ else
exit 1
fi
#--------------------------------------------------------------------------
# perl check
#
PERL=`findtool perl`
# ------------------------------------------------------------
@@ -164,8 +183,13 @@ echo "buildconf: running libtoolize"
${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The libtool command failed"
echo "buildconf: running aclocal"
${ACLOCAL:-aclocal} $ACLOCAL_FLAGS || die "The aclocal command line failed"
echo "buildconf: running aclocal hack to convert all mv to mv -f"
perl -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4
if test -n "$PERL"; then
echo "buildconf: running aclocal hack to convert all mv to mv -f"
$PERL -i.bak -pe 's/\bmv +([^-\s])/mv -f $1/g' aclocal.m4
else
echo "buildconf: perl not found"
exit 1
fi
echo "buildconf: running autoheader"
${AUTOHEADER:-autoheader} || die "The autoheader command failed"
echo "buildconf: cp lib/config.h.in src/config.h.in"

View File

@@ -7,7 +7,7 @@ dnl We don't know the version number "staticly" so we use a dash here
AC_INIT(curl, [-], [a suitable curl mailing list => http://curl.haxx.se/mail/])
dnl configure script copyright
AC_COPYRIGHT([Copyright (c) 1998 - 2004 Daniel Stenberg, <daniel@haxx.se>
AC_COPYRIGHT([Copyright (c) 1998 - 2005 Daniel Stenberg, <daniel@haxx.se>
This configure script may be copied, distributed and modified under the
terms of the curl license; see COPYING for more details])
@@ -56,7 +56,7 @@ AC_SUBST(PKGADD_VENDOR)
dnl
dnl initialize all the info variables
curl_ssl_msg="no (--with-ssl)"
curl_ssl_msg="no (--with-ssl / --with-gnutls)"
curl_zlib_msg="no (--with-zlib)"
curl_krb4_msg="no (--with-krb4*)"
curl_gss_msg="no (--with-gssapi)"
@@ -747,11 +747,7 @@ AC_HELP_STRING([--with-ssl=PATH],[where to look for SSL, PATH points to the SSL
AC_HELP_STRING([--without-ssl], [disable SSL]),
OPT_SSL=$withval)
if test X"$OPT_SSL" = Xno
then
AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more])
else
if test X"$OPT_SSL" != Xno; then
dnl backup the pre-ssl variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -868,13 +864,13 @@ else
dnl Have the libraries--check for SSLeay/OpenSSL headers
AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
openssl/pem.h openssl/ssl.h openssl/err.h,
curl_ssl_msg="enabled"
curl_ssl_msg="enabled (OpenSSL)"
OPENSSL_ENABLED=1
AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use]))
if test $ac_cv_header_openssl_x509_h = no; then
AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h,
curl_ssl_msg="enabled"
curl_ssl_msg="enabled (OpenSSL)"
OPENSSL_ENABLED=1)
fi
fi
@@ -989,6 +985,79 @@ if test X"$OPENSSL_ENABLED" = X"1"; then
fi
fi
dnl ----------------------------------------------------
dnl FIX: only check for GnuTLS if OpenSSL is not enabled
dnl ----------------------------------------------------
dnl Default to compiler & linker defaults for GnuTLS files & libraries.
OPT_GNUTLS=off
AC_ARG_WITH(gnutls,dnl
AC_HELP_STRING([--with-gnutls=PATH],[where to look for GnuTLS, PATH points to the installation root (default: /usr/local/)])
AC_HELP_STRING([--without-gnutls], [disable GnuTLS detection]),
OPT_GNUTLS=$withval)
if test "$OPENSSL_ENABLED" != "1"; then
if test X"$OPT_GNUTLS" != Xoff; then
if test "x$OPT_GNUTLS" = "xyes"; then
check=`libgnutls-config --version 2>/dev/null`
if test -n "$check"; then
addlib=`libgnutls-config --libs`
addcflags=`libgnutls-config --cflags`
version=`libgnutls-config --version`
gtlsprefix=`libgnutls-config --prefix`
fi
else
addlib="-L$OPT_GNUTLS/lib -lgnutls"
addcflags="-I$OPT_GNUTLS/include"
version=`$OPT_GNUTLS/bin/libgnutls-config --version 2>/dev/null`
gtlsprefix=$OPT_GNUTLS
if test -z "$version"; then
version="unknown"
fi
fi
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
LDFLAGS="$LDFLAGS $addlib"
if test "$addcflags" != "-I/usr/include"; then
CPPFLAGS="$CPPFLAGS $addcflags"
fi
AC_CHECK_LIB(gnutls, gnutls_check_version,
[
AC_DEFINE(USE_GNUTLS, 1, [if GnuTLS is enabled])
AC_SUBST(USE_GNUTLS, [1])
USE_GNUTLS="yes"
curl_ssl_msg="enabled (GnuTLS)"
],
[
LDFLAGS="$CLEANLDFLAGS"
CPPFLAGS="$CLEANCPPFLAGS"
])
if test "x$USE_GNUTLS" = "xyes"; then
AC_MSG_NOTICE([detected GnuTLS version $version])
dnl when shared libs were found in a path that the run-time
dnl linker doesn't search through, we need to add it to
dnl LD_LIBRARY_PATH to prevent further configure tests to fail
dnl due to this
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$gtlsprefix/lib$libsuff"
export LD_LIBRARY_PATH
fi
fi dnl GNUTLS not disabled
if test X"$USE_GNUTLS" != "Xyes"; then
AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
AC_MSG_WARN([Use --with-ssl or --with-gnutls to address this.])
fi
fi dnl OPENSSL != 1
dnl **********************************************************************
dnl Check for the presence of ZLIB libraries and headers
dnl **********************************************************************

View File

@@ -1,4 +1,4 @@
Updated: December 21, 2004 (http://curl.haxx.se/docs/faq.html)
Updated: April 13, 2005 (http://curl.haxx.se/docs/faq.html)
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
@@ -43,6 +43,7 @@ FAQ
3.15 Can I do recursive fetches with curl?
3.16 What certificates do I need when I use SSL?
3.17 How do I list the root dir of an FTP server?
3.18 Can I use curl to send a POST/PUT and not wait for a response?
4. Running Problems
4.1 Problems connecting to SSL servers.
@@ -74,6 +75,9 @@ FAQ
5.7 Link errors when building libcurl on Windows!
5.8 libcurl.so.3: open failed: No such file or directory
5.9 How does libcurl resolve host names?
5.10 How do I prevent libcurl from writing the response to stdout?
5.11 How do I make libcurl not receive the whole HTTP response?
5.12 Can I make libcurl fake or hide my real IP address?
6. License Issues
6.1 I have a GPL program, can I use the libcurl library?
@@ -97,7 +101,7 @@ FAQ
cURL is the name of the project. The name is a play on 'Client for URLs',
originally with URL spelled in uppercase to make it obvious it deals with
URLs. The fact it can also be pronounced 'see URL' also helped, it works as
an abbrivation for "Client URL Request Library" or why not the recursive
an abbreviation for "Client URL Request Library" or why not the recursive
version: "Curl URL Request Library".
The cURL project produces two products:
@@ -296,8 +300,8 @@ FAQ
2.2 Does curl work/build with other SSL libraries?
Curl has been written to use OpenSSL, although there should not be much
problems using a different library. If anyone does "port" curl to use a
Curl has been written to use OpenSSL or GnuTLS, although there should not be
many problems using a different library. If anyone does "port" curl to use a
different SSL library, we are of course very interested in getting the
patch!
@@ -503,9 +507,9 @@ FAQ
If the server doesn't require this, you don't need a client certificate.
- Server certificate. The server you communicate with has a server
certificate. You can and should verify this certficate to make sure that
certificate. You can and should verify this certificate to make sure that
you are truly talking to the real server and not a server impersonating
it. The server certificate verifaction process is made by using a
it. The server certificate verification process is made by using a
Certificate Authority certificate ("CA cert") that was used to sign the
server certificate. Server certificate verification is enabled by default
in curl and libcurl and is often the reason for problems as explained in
@@ -533,6 +537,10 @@ FAQ
curl ftp://ftp.sunet.se//tmp/
3.18 Can I use curl to send a POST/PUT and not wait for a response?
No.
4. Running Problems
@@ -733,12 +741,20 @@ FAQ
Yes.
We have written the libcurl code specificly adjusted for multi-threaded
We have written the libcurl code specifically adjusted for multi-threaded
programs. libcurl will use thread-safe functions instead of non-safe ones if
your system has such.
We would appreciate some kind of report or README file from those who have
used libcurl in a threaded environment.
If you use a OpenSSL-powered libcurl in a multi-threaded environment, you
need to provide one or two locking functions:
http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
If you use a GnuTLS-powered libcurl in a multi-threaded environment, you
need to provide locking function(s) for libgcrypt (which is used by GnuTLS
for the crypto functions).
[informative link missing]
5.2 How can I receive all data into a large memory chunk?
@@ -877,6 +893,35 @@ FAQ
A - gethostbyname() on plain ipv4 windows hosts
B - getaddrinfo() on ipv6-enabled windows hosts
Also note that libcurl never resolves or reverse-lookups addresses given as
pure numbers, such as 127.0.0.1 or ::1.
5.10 How do I prevent libcurl from writing the response to stdout?
libcurl provides a default built-in write function that writes received data
to stdout. Set a WRITEFUNCTION to receive the data, or possibly set
WRITEDATA to a different FILE * handle.
5.11 How do I make libcurl not receive the whole HTTP response?
You make the write callback (or progress callback) return an error and
libcurl will then abort the transfer.
5.12 Can I make libcurl fake or hide my real IP address?
No. libcurl operates on a higher level than so. Besides, faking IP address
would imply sending IP packages with a made-up source address, and then you
normally get a problem with intercepting the packages sent back as they
would then not be routed to you!
If you use a proxy to access remote sites, the sites will not see your local
IP address but instead the address of the proxy.
Also note that on many networks NATs or other IP-munging techniques are used
that makes you see and use a different IP address locally than what the
remote server will see you coming from.
6. License Issues
Curl and libcurl are released under a MIT/X derivate license. The license is

View File

@@ -139,3 +139,7 @@ August 2004:
Number of public functions in libcurl: 36
Amount of public web site mirrors: 12
Number of known libcurl bindings: 26
April 2005:
GnuTLS can now optionally be used for the secure layer when curl is built.

View File

@@ -32,7 +32,15 @@ OpenSSL http://www.openssl.org/source/license.html
makes it "incompatible" with GPL. You are not allowed to ship binaries
that link with OpenSSL that includes GPL code (unless that specific
GPL code includes an exception for OpenSSL - a habit that is growing
more and more common).
more and more common). If OpenSSL's licensing is a problem for you,
consider using GnuTLS instead.
GnuTLS http://www.gnutls.org/
Uses the LGPL[3] license. If this is a problem for you, consider using
OpenSSL instead. Also note that GnuTLS itself depends on and uses
other libs (libgcrypt and libgpg-error) and they too are LGPL- or
GPL-licensed.
c-ares http://daniel.haxx.se/projects/c-ares/license.html
@@ -84,3 +92,5 @@ OpenLDAP http://www.openldap.org/software/release/license.html
[1] = GPL - GNU General Public License: http://www.gnu.org/licenses/gpl.html
[2] = http://www.fsf.org/licenses/gpl-faq.html#GPLIncompatibleLibs details on
how to write such an exception to the GPL
[3] = LGPL - GNU Lesser General Public License:
http://www.gnu.org/licenses/lgpl.html

View File

@@ -26,7 +26,7 @@ TODO
* More data sharing. curl_share_* functions already exist and work, and they
can be extended to share more. For example, enable sharing of the ares
channel.
channel and the connection cache.
* Introduce a new error code indicating authentication problems (for proxy
CONNECT error 407 for example). This cannot be an error code, we must not
@@ -35,16 +35,15 @@ TODO
* Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and
SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete.
To support ipv6 interface addresses properly.
* Add the following to curl_easy_getinfo(): GET_HTTP_IP, GET_FTP_IP and
GET_FTP_DATA_IP. Return a string with the used IP. Suggested by Alan.
LIBCURL - multi interface
* Add a curl_multi_fdset() alternative that returns only two arrays with file
desrciptors for reading and writing to allow the app to use whatever
function it prefers. Plus, this allows apps to avoid the FD_SETSIZE problem
with select().
* Add a curl_multi_fdset() alternative. this allows apps to avoid the
FD_SETSIZE problem with select().
* Add curl_multi_timeout() to make libcurl's ares-functionality better.
@@ -68,9 +67,6 @@ TODO
* Make the detection of (bad) %0d and %0a codes in FTP url parts earlier in
the process to avoid doing a resolve and connect in vain.
* Code overhaul to make it more state-machine like and to _never_ block on
waiting for server responses when used with the multi interface.
* Support GSS/Kerberos 5 for ftp file transfer. This will allow user
authentication and file encryption. Possible libraries and example clients
are available from MIT or Heimdal. Requsted by Markus Moeller.
@@ -146,14 +142,9 @@ TODO
it be? There's so much that could be done if it were! (brought by Chris
Clark)
* Make curl's SSL layer option capable of using other free SSL libraries.
Such as the Mozilla Security Services
(http://www.mozilla.org/projects/security/pki/nss/) and GnuTLS
(http://www.gnu.org/software/gnutls/) This subject has been brought up
again recently since GPL-licensed applications that link with libcurl MAY
NOT distribute binaries that use OpenSSL without adding an exception clause
to the GPL license. See the LICENSE-MIXING document and this:
http://www.gnome.org/~markmc/openssl-and-the-gpl.html
* Make curl's SSL layer capable of using other free SSL libraries. Such as
the Mozilla Security Services:
http://www.mozilla.org/projects/security/pki/nss/
LDAP

View File

@@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
.TH curl 1 "29 Mar 2005" "Curl 7.13.2" "Curl Manual"
.TH curl 1 "05 Apr 2005" "Curl 7.13.3" "Curl Manual"
.SH NAME
curl \- transfer a URL
.SH SYNOPSIS
@@ -887,9 +887,9 @@ This option may be used any number of times. To control where this URL is
written, use the \fI-o/--output\fP or the \fI-O/--remote-name\fP options.
.IP "-v/--verbose"
Makes the fetching more verbose/talkative. Mostly usable for debugging. Lines
starting with '>' means data sent by curl, '<' means data received by curl
that is hidden in normal cases and lines starting with '*' means additional
info provided by curl.
starting with '>' means data sent by curl (this data may in itself contain
newlines), '<' means data received by curl that is hidden in normal cases and
lines starting with '*' means additional info provided by curl.
Note that if you only want HTTP headers in the output, \fI-i/--include\fP
might be option you're looking for.
@@ -933,6 +933,9 @@ SPNEGO Negotiate authentication is supported.
This curl supports transfers of large files, files larger than 2GB.
.IP "IDN"
This curl supports IDN - international domain names.
.IP "SSPI"
SSPI is supported. If you use NTLM and set a blank user name, curl will
authenticate with your current user and password.
.RE
.IP "-w/--write-out <format>"
Defines what to display after a completed and successful operation. The format
@@ -1284,5 +1287,5 @@ http://curl.haxx.se
ftp://ftp.sunet.se/pub/www/utilities/curl/
.SH "SEE ALSO"
.BR ftp (1),
.BR wget (1),
.BR wget (1)

View File

@@ -1,6 +1,6 @@
.\" $Id$
.\"
.TH curl_multi_fdset 3 "15 Apr 2004" "libcurl 7.9.5" "libcurl Manual"
.TH curl_multi_fdset 3 "18 Apr 2005" "libcurl 7.9.5" "libcurl Manual"
.SH NAME
curl_multi_fdset - extracts file descriptor information from a multi handle
.SH SYNOPSIS
@@ -15,15 +15,17 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
.ad
.SH DESCRIPTION
This function extracts file descriptor information from a given multi_handle.
libcurl returns its fd_set sets. The application can use these to select()
on. The \fIcurl_multi_perform(3)\fP function should be called as soon as one
of them are ready to be read from or written to.
libcurl returns its fd_set sets. The application can use these to select() on,
but be sure to FD_ZERO them before calling this function as
\fIcurl_multi_fdset(3)\fP only adds its own descriptors it doesn't zero or
otherwise remove any other. The \fIcurl_multi_perform(3)\fP function should be
called as soon as one of them are ready to be read from or written to.
You should also be aware that when doing select(), you should consider using a
rather small (single-digit number of seconds) timeout and call
\fIcurl_multi_perform\fP regularly - even if no activity has been seen on the
fd_sets - as otherwise libcurl-internal retries and timeouts may not work as
you'd think.
you'd think and want.
.SH RETURN VALUE
CURLMcode type, general libcurl multi interface error code. See
\fIlibcurl-errors(3)\fP

View File

@@ -34,7 +34,7 @@ typedef struct {
const char *host; /* human readable string */
int features; /* bitmask, see below */
char *ssl_version; /* human readable string */
long ssl_version_num; /* number */
long ssl_version_num; /* not used, always zero */
const char *libz_version; /* human readable string */
const char **protocols; /* list of protocols */

View File

@@ -1358,8 +1358,8 @@ typedef struct {
const char *host; /* OS/host/cpu/machine when configured */
int features; /* bitmask, see defines below */
const char *ssl_version; /* human readable string */
long ssl_version_num; /* number */
const char *libz_version; /* human readable string */
long ssl_version_num; /* not used anymore, always 0 */
const char *libz_version; /* human readable string */
/* protocols is terminated by an entry with a NULL protoname */
const char * const *protocols;

View File

@@ -28,7 +28,7 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.13.2-CVS"
#define LIBCURL_VERSION "7.14.0-CVS"
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -44,12 +44,12 @@
always a greater number in a more recent release. It makes comparisons with
greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x070d02
#define LIBCURL_VERSION_NUM 0x070e00
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 13
#define LIBCURL_VERSION_PATCH 2
#define LIBCURL_VERSION_MINOR 14
#define LIBCURL_VERSION_PATCH 0
#endif /* __CURL_CURLVER_H */

View File

@@ -43,7 +43,8 @@ OBJS = $(OBJ_DIR)\transfer.obj $(OBJ_DIR)\file.obj &
$(OBJ_DIR)\hostip4.obj $(OBJ_DIR)\hostthre.obj &
$(OBJ_DIR)\hostip6.obj $(OBJ_DIR)\inet_ntop.obj &
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.obj &
$(OBJ_DIR)\select.obj
$(OBJ_DIR)\select.obj $(OBJ_DIR)\sslgen.obj &
$(OBJ_DIR)\gtls.obj
RESOURCE = $(OBJ_DIR)\libcurl.res
@@ -355,3 +356,9 @@ $(OBJ_DIR)\parsedate.obj: parsedate.c setup.h config-win32.h ..\include\curl\cur
..\include\curl\multi.h ..\include\curl\curl.h
$(OBJ_DIR)\select.obj: select.c setup.h config-win32.h select.h
$(OBJ_DIR)\gtls.obj: gtls.c setup.h config-win32.h
$(OBJ_DIR)\sslgen.obj: sslgen.c setup.h config-win32.h urldata.h cookie.h &
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sslgen.h &
ssluse.h gtls.h sendf.h strequal.h url.h memory.h memdebug.h

View File

@@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
select.c
select.c gtls.c sslgen.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -17,4 +17,6 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
http_chunks.h strtok.h connect.h llist.h hash.h content_encoding.h \
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
setup.h transfer.h select.h easyif.h multiif.h parsedate.h
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
gtls.h

View File

@@ -12,7 +12,7 @@ objs = o.base64 o.connect o.cookie o.dict \
o.memdebug o.mprintf o.netrc o.parsedate o.progress \
o.security o.select o.sendf o.speedcheck o.ssluse \
o.strequal o.strtok o.telnet o.timeval \
o.transfer o.url o.version o.strtoofft
o.transfer o.url o.version o.strtoofft o.sslgen o.gtls
# Compile options:
linkopts = -o libcurl
@@ -119,6 +119,12 @@ o.sendf: c.sendf
o.speedcheck: c.speedcheck
gcc $(compileropts) -c -o speedcheck.o c.speedcheck
o.gtls: c.gtls
gcc $(compileropts) -c -o gtls.o c.gtls
o.sslgen: c.sslgen
gcc $(compileropts) -c -o sslgen.o c.sslgen
o.ssluse: c.ssluse
gcc $(compileropts) -c -o ssluse.o c.ssluse

View File

@@ -428,6 +428,7 @@ X_OBJS= \
$(DIROBJ)\telnet.obj \
$(DIROBJ)\parsedate.obj \
$(DIROBJ)\getenv.obj \
$(DIROBJ)\gtls.obj \
$(DIROBJ)\inet_pton.obj \
$(DIROBJ)\hostip.obj \
$(DIROBJ)\hostasyn.obj \
@@ -443,6 +444,7 @@ X_OBJS= \
$(DIROBJ)\progress.obj \
$(DIROBJ)\sendf.obj \
$(DIROBJ)\speedcheck.obj \
$(DIROBJ)\sslgen.obj \
$(DIROBJ)\ssluse.obj \
$(DIROBJ)\timeval.obj \
$(DIROBJ)\url.obj \

17
lib/TODO.gnutls Normal file
View File

@@ -0,0 +1,17 @@
Things to fix for the GnuTLS support
====================================
* make the configure --with-ssl option first check for OpenSSL and then for
GnuTLS if OpenSSL wasn't detected.
* Get NTLM working using the functions provided by libgcrypt, since GnuTLS
already depends on that to function. Not strictly SSL/TLS related, but
hey... Another option is to get available DES and MD4 source code from the
cryptopp library. They are fine license-wise, but are C++.
* SSL engine stuff?
SRP for TLS
* Work out a common method with Peter Sylvester's OpenSSL-patch for SRP
on the TLS to provide name and password

View File

@@ -75,7 +75,7 @@
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "ssluse.h"
#include "sslgen.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
@@ -201,7 +201,7 @@ CURLcode curl_global_init(long flags)
Curl_ccalloc = (curl_calloc_callback)calloc;
if (flags & CURL_GLOBAL_SSL)
if (!Curl_SSL_init())
if (!Curl_ssl_init())
return CURLE_FAILED_INIT;
if (flags & CURL_GLOBAL_WIN32)
@@ -266,7 +266,7 @@ void curl_global_cleanup(void)
Curl_global_host_cache_dtor();
if (init_flags & CURL_GLOBAL_SSL)
Curl_SSL_cleanup();
Curl_ssl_cleanup();
if (init_flags & CURL_GLOBAL_WIN32)
win32_cleanup();

View File

@@ -87,7 +87,7 @@
#include "strtoofft.h"
#include "strequal.h"
#include "ssluse.h"
#include "sslgen.h"
#include "connect.h"
#include "strerror.h"
#include "memory.h"
@@ -2013,7 +2013,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
/* BLOCKING */
result = Curl_SSLConnect(conn, SECONDARYSOCKET);
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
if(result)
return result;
}
@@ -2121,7 +2121,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
/* since we only have a plaintext TCP connection here, we must now
do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
result = Curl_SSLConnect(conn, SECONDARYSOCKET);
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
if(result)
return result;
}
@@ -2373,8 +2373,8 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
*/
if((ftpcode == 234) || (ftpcode == 334)) {
/* Curl_SSLConnect is BLOCKING */
result = Curl_SSLConnect(conn, FIRSTSOCKET);
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(CURLE_OK == result) {
conn->protocol |= PROT_FTPS;
conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
@@ -2748,7 +2748,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn,
/* BLOCKING */
/* FTPS is simply ftp with SSL for the control channel */
/* now, perform the SSL initialization for this socket */
result = Curl_SSLConnect(conn, FIRSTSOCKET);
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result)
return result;
}
@@ -2820,7 +2820,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status)
if(data->set.upload) {
if((-1 != data->set.infilesize) &&
(data->set.infilesize != *ftp->bytecountp) &&
!data->set.crlf) {
!data->set.crlf &&
!ftp->no_transfer) {
failf(data, "Uploaded unaligned file size (%" FORMAT_OFF_T
" out of %" FORMAT_OFF_T " bytes)",
*ftp->bytecountp, data->set.infilesize);

View File

@@ -33,7 +33,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include "memory.h"
#include "ssluse.h"
#include "sslgen.h"
/* Make this the last #include */
#include "memdebug.h"
@@ -182,7 +182,7 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
*param_longp = data->info.numconnects;
break;
case CURLINFO_SSL_ENGINES:
*param_slistp = Curl_SSL_engines_list(data);
*param_slistp = Curl_ssl_engines_list(data);
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;

486
lib/gtls.c Normal file
View File

@@ -0,0 +1,486 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
/*
* Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
* but sslgen.c should ever call or use these functions.
*
* Note: don't use the GnuTLS' *_t variable type names in this source code,
* since they were not present in 1.0.X.
*/
#include "setup.h"
#ifdef USE_GNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "gtls.h"
#include "sslgen.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
#ifdef GTLSDEBUG
static void tls_log_func(int level, const char *str)
{
fprintf(stderr, "|<%d>| %s", level, str);
}
#endif
/* Global GnuTLS init, called from Curl_ssl_init() */
int Curl_gtls_init(void)
{
gnutls_global_init();
#ifdef GTLSDEBUG
gnutls_global_set_log_function(tls_log_func);
gnutls_global_set_log_level(2);
#endif
return 1;
}
int Curl_gtls_cleanup(void)
{
gnutls_global_deinit();
return 1;
}
static void showtime(struct SessionHandle *data,
const char *text,
time_t stamp)
{
struct tm *tm;
#ifdef HAVE_GMTIME_R
struct tm buffer;
tm = (struct tm *)gmtime_r(&stamp, &buffer);
#else
tm = gmtime(&stamp);
#endif
snprintf(data->state.buffer,
BUFSIZE,
"\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
text,
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
Curl_month[tm->tm_mon],
tm->tm_year + 1900,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
infof(data, "%s", data->state.buffer);
}
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic.
*/
CURLcode
Curl_gtls_connect(struct connectdata *conn,
int sockindex)
{
const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
struct SessionHandle *data = conn->data;
gnutls_session session;
int rc;
unsigned int cert_list_size;
const gnutls_datum *chainp;
unsigned int verify_status;
gnutls_x509_crt x509_cert;
char certbuf[256]; /* big enough? */
size_t size;
unsigned int algo;
unsigned int bits;
time_t clock;
const char *ptr;
void *ssl_sessionid;
size_t ssl_idsize;
/* GnuTLS only supports TLSv1 (and SSLv3?) */
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
/* allocate a cred struct */
rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
if(rc < 0) {
failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
}
if(data->set.ssl.CAfile) {
/* set the trusted CA cert bundle file */
rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
data->set.ssl.CAfile,
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)\n",
data->set.ssl.CAfile, gnutls_strerror(rc));
}
}
/* Initialize TLS session as a client */
rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
if(rc) {
failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
/* convenient assign */
session = conn->ssl[sockindex].session;
/* Use default priorities */
rc = gnutls_set_default_priority(session);
if(rc < 0)
return CURLE_SSL_CONNECT_ERROR;
/* Sets the priority on the certificate types supported by gnutls. Priority
is higher for types specified before others. After specifying the types
you want, you must append a 0. */
rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
if(rc < 0)
return CURLE_SSL_CONNECT_ERROR;
/* put the anonymous credentials to the current session */
rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
conn->ssl[sockindex].cred);
/* set the connection handle (file descriptor for the socket) */
gnutls_transport_set_ptr(session,
(gnutls_transport_ptr)conn->sock[sockindex]);
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
/* we got a session id, use it! */
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
/* Informational message */
infof (data, "SSL re-using session ID\n");
}
do {
rc = gnutls_handshake(session);
if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
long timeout_ms;
long has_passed;
if(data->set.timeout || data->set.connecttimeout) {
/* get the most strict timeout of the ones converted to milliseconds */
if(data->set.timeout &&
(data->set.timeout>data->set.connecttimeout))
timeout_ms = data->set.timeout*1000;
else
timeout_ms = data->set.connecttimeout*1000;
}
else
timeout_ms = DEFAULT_CONNECT_TIMEOUT;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
/* subtract the passed time */
timeout_ms -= has_passed;
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEOUTED;
}
rc = Curl_select(conn->sock[sockindex],
conn->sock[sockindex], (int)timeout_ms);
if(rc > 0)
/* reabable or writable, go loop*/
continue;
else if(0 == rc) {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select on SSL socket, errno: %d", Curl_ourerrno());
return CURLE_SSL_CONNECT_ERROR;
}
}
else
break;
} while(1);
if (rc < 0) {
failf(data, "gnutls_handshake() failed: %d", rc);
/* gnutls_perror(ret); */
return CURLE_SSL_CONNECT_ERROR;
}
/* This function will return the peer's raw certificate (chain) as sent by
the peer. These certificates are in raw format (DER encoded for
X.509). In case of a X.509 then a certificate list may be present. The
first certificate in the list is the peer's certificate, following the
issuer's certificate, then the issuer's issuer etc. */
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
if(!chainp) {
if(data->set.ssl.verifyhost) {
failf(data, "failed to get server cert");
return CURLE_SSL_PEER_CERTIFICATE;
}
infof(data, "\t common name: WARNING couldn't obtain\n");
}
/* This function will try to verify the peer's certificate and return its
status (trusted, invalid etc.). The value of status should be one or more
of the gnutls_certificate_status_t enumerated elements bitwise or'd. To
avoid denial of service attacks some default upper limits regarding the
certificate key size and chain size are set. To override them use
gnutls_certificate_set_verify_limits(). */
rc = gnutls_certificate_verify_peers2(session, &verify_status);
if (rc < 0) {
failf(data, "server cert verify failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
/* verify_status is a bitmask of gnutls_certificate_status bits */
if(verify_status & GNUTLS_CERT_INVALID) {
if (data->set.ssl.verifypeer) {
failf(data, "server certificate verification failed. CAfile: %s",
data->set.ssl.CAfile?data->set.ssl.CAfile:"none");
return CURLE_SSL_CACERT;
}
else
infof(data, "\t server certificate verification FAILED\n");
}
else
infof(data, "\t server certificate verification OK\n");
/* initialize an X.509 certificate structure. */
gnutls_x509_crt_init(&x509_cert);
/* convert the given DER or PEM encoded Certificate to the native
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
size=sizeof(certbuf);
rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
0, /* the first and only one */
TRUE, /* give to me raw please */
certbuf,
&size);
/* This function will check if the given certificate's subject matches the
given hostname. This is a basic implementation of the matching described
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
alternative name PKIX extension. Returns non zero on success, and zero on
failure. */
rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
if(!rc) {
if (data->set.ssl.verifyhost > 1) {
failf(data, "SSL: certificate subject name (%s) does not match "
"target host name '%s'", certbuf, conn->host.dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_PEER_CERTIFICATE;
}
else
infof(data, "\t common name: %s (does not match '%s')\n",
certbuf, conn->host.dispname);
}
else
infof(data, "\t common name: %s (matched)\n", certbuf);
/* Show:
- ciphers used
- subject
- start date
- expire date
- common name
- issuer
*/
/* public key algorithm's parameters */
algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
infof(data, "\t certificate public key: %s\n",
gnutls_pk_algorithm_get_name(algo));
/* version of the X.509 certificate. */
infof(data, "\t certificate version: #%d\n",
gnutls_x509_crt_get_version(x509_cert));
size = sizeof(certbuf);
gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
infof(data, "\t subject: %s\n", certbuf);
clock = gnutls_x509_crt_get_activation_time(x509_cert);
showtime(data, "start date", clock);
clock = gnutls_x509_crt_get_expiration_time(x509_cert);
showtime(data, "expire date", clock);
size = sizeof(certbuf);
gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
infof(data, "\t issuer: %s\n", certbuf);
gnutls_x509_crt_deinit(x509_cert);
/* compression algorithm (if any) */
ptr = gnutls_compression_get_name(gnutls_compression_get(session));
/* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
infof(data, "\t compression: %s\n", ptr);
/* the name of the cipher used. ie 3DES. */
ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
infof(data, "\t cipher: %s\n", ptr);
/* the MAC algorithms name. ie SHA1 */
ptr = gnutls_mac_get_name(gnutls_mac_get(session));
infof(data, "\t MAC: %s\n", ptr);
if(!ssl_sessionid) {
/* this session was not previously in the cache, add it now */
/* get the session ID data size */
gnutls_session_get_data(session, NULL, &ssl_idsize);
ssl_sessionid = malloc(ssl_idsize); /* get a buffer for it */
if(ssl_sessionid) {
/* extract session ID to the allocated buffer */
gnutls_session_get_data(session, ssl_sessionid, &ssl_idsize);
/* store this session id */
return Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_idsize);
}
}
return CURLE_OK;
}
/* return number of sent (non-SSL) bytes */
int Curl_gtls_send(struct connectdata *conn,
int sockindex,
void *mem,
size_t len)
{
int rc;
rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
return rc;
}
void Curl_gtls_close_all(struct SessionHandle *data)
{
/* FIX: make the OpenSSL code more generic and use parts of it here */
(void)data;
}
static void close_one(struct connectdata *conn,
int index)
{
if(conn->ssl[index].session) {
gnutls_bye(conn->ssl[index].session, GNUTLS_SHUT_RDWR);
gnutls_deinit(conn->ssl[index].session);
}
gnutls_certificate_free_credentials(conn->ssl[index].cred);
}
void Curl_gtls_close(struct connectdata *conn)
{
if(conn->ssl[0].use)
close_one(conn, 0);
if(conn->ssl[1].use)
close_one(conn, 1);
}
/*
* If the read would block we return -1 and set 'wouldblock' to TRUE.
* Otherwise we return the amount of data read. Other errors should return -1
* and set 'wouldblock' to FALSE.
*/
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool *wouldblock)
{
ssize_t ret;
ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*wouldblock = TRUE;
return -1;
}
*wouldblock = FALSE;
if (!ret) {
failf(conn->data, "Peer closed the TLS connection");
return -1;
}
if (ret < 0) {
failf(conn->data, "GnuTLS recv error (%d): %s",
(int)ret, gnutls_strerror(ret));
return -1;
}
return ret;
}
void Curl_gtls_session_free(void *ptr)
{
free(ptr);
}
size_t Curl_gtls_version(char *buffer, size_t size)
{
return snprintf(buffer, size, " GnuTLS/%s", gnutls_check_version(NULL));
}
#endif /* USE_GNUTLS */

45
lib/gtls.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __GTLS_H
#define __GTLS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
int Curl_gtls_init(void);
int Curl_gtls_cleanup(void);
CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
/* tell GnuTLS to close down all open information regarding connections (and
thus session ID caching etc) */
void Curl_gtls_close_all(struct SessionHandle *data);
void Curl_gtls_close(struct connectdata *conn); /* close a SSL connection */
/* return number of sent (non-SSL) bytes */
int Curl_gtls_send(struct connectdata *conn, int sockindex,
void *mem, size_t len);
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool *wouldblock);
void Curl_gtls_session_free(void *ptr);
size_t Curl_gtls_version(char *buffer, size_t size);
#endif

View File

@@ -85,7 +85,7 @@
#include "base64.h"
#include "cookie.h"
#include "strequal.h"
#include "ssluse.h"
#include "sslgen.h"
#include "http_digest.h"
#include "http_ntlm.h"
#include "http_negotiate.h"
@@ -416,7 +416,7 @@ Curl_http_output_auth(struct connectdata *conn,
/* Send proxy authentication header if needed */
if (conn->bits.httpproxy &&
(conn->bits.tunnel_proxy == proxytunnel)) {
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
#ifdef USE_NTLM
if(authproxy->picked == CURLAUTH_NTLM) {
auth=(char *)"NTLM";
result = Curl_output_ntlm(conn, TRUE);
@@ -484,7 +484,7 @@ Curl_http_output_auth(struct connectdata *conn,
}
else
#endif
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
#ifdef USE_NTLM
if(authhost->picked == CURLAUTH_NTLM) {
auth=(char *)"NTLM";
result = Curl_output_ntlm(conn, FALSE);
@@ -597,7 +597,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
}
else
#endif
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
#ifdef USE_NTLM
/* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", start)) {
*availp |= CURLAUTH_NTLM;
@@ -1268,8 +1268,8 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
}
if(conn->protocol & PROT_HTTPS) {
/* now, perform the SSL initialization for this socket */
result = Curl_SSLConnect(conn, FIRSTSOCKET);
/* perform SSL initialization for this socket */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(result)
return result;
}

View File

@@ -30,8 +30,7 @@
*/
#ifndef CURL_DISABLE_HTTP
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
/* We need OpenSSL for the crypto lib to provide us with MD4 and DES */
#ifdef USE_NTLM
/* -- WIN32 approved -- */
#include <stdio.h>
@@ -769,5 +768,5 @@ Curl_ntlm_cleanup(struct connectdata *conn)
#endif
}
#endif /* USE_SSLEAY */
#endif /* USE_NTLM */
#endif /* !CURL_DISABLE_HTTP */

View File

@@ -39,6 +39,9 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header);
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
void Curl_ntlm_cleanup(struct connectdata *conn);
#if !defined(USE_SSLEAY) && !defined(USE_WINDOWS_SSPI)
#define Curl_ntlm_cleanup(x)
#endif
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */

View File

@@ -110,7 +110,7 @@ char *Curl_if2ip(const char *interface, char *buf, int buf_size)
struct sockaddr_in *s = (struct sockaddr_in *)&req.ifr_dstaddr;
memcpy(&in, &(s->sin_addr.s_addr), sizeof(in));
ip = Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
ip = (char *) Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
}
sclose(dummy);
}

View File

@@ -43,6 +43,7 @@ OBJECTS = $(TMP_DIR)/base64.o \
$(TMP_DIR)/ftp.o \
$(TMP_DIR)/getenv.o \
$(TMP_DIR)/getinfo.o \
$(TMP_DIR)/gtls.o \
$(TMP_DIR)/hash.o \
$(TMP_DIR)/hostares.o \
$(TMP_DIR)/hostasyn.o \
@@ -73,6 +74,7 @@ OBJECTS = $(TMP_DIR)/base64.o \
$(TMP_DIR)/sendf.o \
$(TMP_DIR)/share.o \
$(TMP_DIR)/speedcheck.o \
$(TMP_DIR)/sslgen.o \
$(TMP_DIR)/ssluse.o \
$(TMP_DIR)/strequal.o \
$(TMP_DIR)/strerror.o \

View File

@@ -10,15 +10,14 @@ ATCPSDKI= /GG/netinclude
CC = gcc
CFLAGS = -I$(ATCPSDKI) -m68020-60 -noixemul -I. -I../include -W -Wall
OBJS = \
amigaos.c base64.c connect.c content_encoding.c cookie.c dict.c \
easy.c escape.c file.c formdata.c ftp.c getenv.c \
getinfo.c hash.c hostip.c hostip4.c hostsyn.c http.c http_chunks.c \
http_digest.c http_negotiate.c http_ntlm.c if2ip.c inet_ntop.c \
inet_pton.c krb4.c ldap.c \
llist.c md5.c memdebug.c mprintf.c multi.c netrc.c parsedate.c \
progress.c security.c select.c sendf.c share.c speedcheck.c \
ssluse.c strequal.c strtok.c telnet.c timeval.c transfer.c url.c version.c
OBJS = amigaos.c base64.c connect.c content_encoding.c cookie.c dict.c easy.c \
escape.c file.c formdata.c ftp.c getenv.c getinfo.c hash.c hostip.c \
hostip4.c hostsyn.c http.c http_chunks.c http_digest.c \
http_negotiate.c http_ntlm.c if2ip.c inet_ntop.c inet_pton.c krb4.c \
ldap.c llist.c md5.c memdebug.c mprintf.c multi.c netrc.c parsedate.c \
progress.c security.c select.c sendf.c share.c speedcheck.c ssluse.c \
strequal.c strtok.c telnet.c timeval.c transfer.c url.c version.c \
sslgen.c gtls.c
all: $(OBJS:.c=.o)
ar cru libcurl.a $(OBJS:.c=.o)

View File

@@ -272,3 +272,7 @@ $(OBJ_DIR)/parsedate.o: parsedate.c setup.h config.h ../include/curl/curl.h \
../include/curl/curlver.h ../include/curl/easy.h \
../include/curl/multi.h
$(OBJ_DIR)/select.o: select.c setup.h config.h select.h
$(OBJ_DIR)/gtls.o: gtls.c setup.h config-win32.h
$(OBJ_DIR)/sslgen.o: sslgen.c setup.h config-win32.h urldata.h cookie.h \
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sslgen.h \
ssluse.h gtls.h sendf.h strequal.h url.h memory.h memdebug.h

View File

@@ -44,13 +44,18 @@
#include "urldata.h"
#include "sendf.h"
#include "connect.h" /* for the Curl_ourerrno() proto */
#include "sslgen.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
#ifdef HAVE_KRB4
#include "krb4.h"
#else
#define Curl_sec_write(a,b,c,d) -1
#define Curl_sec_read(a,b,c,d) -1
#endif
#include <string.h>
#include "memory.h"
#include "strerror.h"
@@ -233,63 +238,18 @@ CURLcode Curl_write(struct connectdata *conn,
{
ssize_t bytes_written;
CURLcode retcode;
#ifdef USE_SSLEAY
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
us use the correct ssl handle. */
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
/* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */
if (conn->ssl[num].use) {
int err;
char error_buffer[120]; /* OpenSSL documents that this must be at least
120 bytes long. */
unsigned long sslerror;
int rc = SSL_write(conn->ssl[num].handle, mem, (int)len);
if(rc < 0) {
err = SSL_get_error(conn->ssl[num].handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* The operation did not complete; the same TLS/SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
*written = 0;
return CURLE_OK;
case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
Curl_ourerrno());
return CURLE_SEND_ERROR;
case SSL_ERROR_SSL:
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
sslerror = ERR_get_error();
failf(conn->data, "SSL_write() error: %s\n",
ERR_error_string(sslerror, error_buffer));
return CURLE_SEND_ERROR;
}
/* a true error */
failf(conn->data, "SSL_write() return error %d\n", err);
return CURLE_SEND_ERROR;
}
bytes_written = rc;
}
if (conn->ssl[num].use)
/* only TRUE if SSL enabled */
bytes_written = Curl_ssl_send(conn, num, mem, len);
else {
#else
(void)conn;
#endif
#ifdef HAVE_KRB4
if(conn->sec_complete) {
if(conn->sec_complete)
/* only TRUE if krb4 enabled */
bytes_written = Curl_sec_write(conn, sockfd, mem, len);
}
else
#endif /* HAVE_KRB4 */
{
bytes_written = (ssize_t)swrite(sockfd, mem, len);
}
if(-1 == bytes_written) {
int err = Curl_ourerrno();
@@ -311,10 +271,7 @@ CURLcode Curl_write(struct connectdata *conn,
failf(conn->data, "Send failure: %s",
Curl_strerror(conn, err));
}
#ifdef USE_SSLEAY
}
#endif
*written = bytes_written;
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
@@ -376,7 +333,7 @@ int Curl_read(struct connectdata *conn, /* connection data */
ssize_t *n) /* amount bytes read */
{
ssize_t nread;
#ifdef USE_SSLEAY
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
us use the correct ssl handle. */
@@ -384,45 +341,17 @@ int Curl_read(struct connectdata *conn, /* connection data */
*n=0; /* reset amount to zero */
if (conn->ssl[num].use) {
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, (int)buffersize);
if(conn->ssl[num].use) {
nread = Curl_ssl_recv(conn, num, buf, buffersize);
if(nread < 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
case SSL_ERROR_ZERO_RETURN: /* no more data */
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */
return -1; /* basicly EWOULDBLOCK */
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
{
char error_buffer[120]; /* OpenSSL documents that this must be at
least 120 bytes long. */
unsigned long sslerror = ERR_get_error();
failf(conn->data, "SSL read: %s, errno %d",
ERR_error_string(sslerror, error_buffer),
Curl_ourerrno() );
}
return CURLE_RECV_ERROR;
}
}
if(nread == -1)
return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
}
else {
#else
(void)conn;
#endif
*n=0; /* reset amount to zero */
#ifdef HAVE_KRB4
if(conn->sec_complete)
nread = Curl_sec_read(conn, sockfd, buf, buffersize);
else
#endif
nread = sread(sockfd, buf, buffersize);
if(-1 == nread) {
@@ -434,10 +363,7 @@ int Curl_read(struct connectdata *conn, /* connection data */
#endif
return -1;
}
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
*n = nread;
return CURLE_OK;
}

View File

@@ -280,4 +280,12 @@ typedef int curl_socket_t;
#define HAVE_INET_NTOA_R_2_ARGS 1
#endif
#if defined(USE_GNUTLS) || defined(USE_SSLEAY)
#define USE_SSL /* Either OpenSSL || GnuTLS */
#endif
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
#define USE_NTLM
#endif
#endif /* __CONFIG_H */

538
lib/sslgen.c Normal file
View File

@@ -0,0 +1,538 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
/* This file is for "generic" SSL functions that all libcurl internals should
use. It is responsible for calling the proper 'ossl' function in ssluse.c
(OpenSSL based) or the 'gtsl' function in gtsl.c (GnuTLS based).
SSL-functions in libcurl should call functions in this source file, and not
to any specific SSL-layer.
Curl_ssl_ - prefix for generic ones
Curl_ossl_ - prefix for OpenSSL ones
Curl_gtls_ - prefix for GnuTLS ones
"SSL/TLS Strong Encryption: An Introduction"
http://httpd.apache.org/docs-2.0/ssl/ssl_intro.html
*/
#include "setup.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include "urldata.h"
#define SSLGEN_C
#include "sslgen.h" /* generic SSL protos etc */
#include "ssluse.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
#include "sendf.h"
#include "strequal.h"
#include "url.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* "global" init done? */
static bool init_ssl=FALSE;
static bool safe_strequal(char* str1, char* str2);
static bool safe_strequal(char* str1, char* str2)
{
if(str1 && str2)
/* both pointers point to something then compare them */
return strequal(str1, str2);
else
/* if both pointers are NULL then treat them as equal */
return (!str1 && !str2);
}
bool
Curl_ssl_config_matches(struct ssl_config_data* data,
struct ssl_config_data* needle)
{
if((data->version == needle->version) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
safe_strequal(data->CApath, needle->CApath) &&
safe_strequal(data->CAfile, needle->CAfile) &&
safe_strequal(data->random_file, needle->random_file) &&
safe_strequal(data->egdsocket, needle->egdsocket) &&
safe_strequal(data->cipher_list, needle->cipher_list))
return TRUE;
return FALSE;
}
bool
Curl_clone_ssl_config(struct ssl_config_data *source,
struct ssl_config_data *dest)
{
dest->verifyhost = source->verifyhost;
dest->verifypeer = source->verifypeer;
dest->version = source->version;
if(source->CAfile) {
dest->CAfile = strdup(source->CAfile);
if(!dest->CAfile)
return FALSE;
}
if(source->CApath) {
dest->CApath = strdup(source->CApath);
if(!dest->CApath)
return FALSE;
}
if(source->cipher_list) {
dest->cipher_list = strdup(source->cipher_list);
if(!dest->cipher_list)
return FALSE;
}
if(source->egdsocket) {
dest->egdsocket = strdup(source->egdsocket);
if(!dest->egdsocket)
return FALSE;
}
if(source->random_file) {
dest->random_file = strdup(source->random_file);
if(!dest->random_file)
return FALSE;
}
return TRUE;
}
void Curl_free_ssl_config(struct ssl_config_data* sslc)
{
if(sslc->CAfile)
free(sslc->CAfile);
if(sslc->CApath)
free(sslc->CApath);
if(sslc->cipher_list)
free(sslc->cipher_list);
if(sslc->egdsocket)
free(sslc->egdsocket);
if(sslc->random_file)
free(sslc->random_file);
}
/**
* Global SSL init
*
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
int Curl_ssl_init(void)
{
/* make sure this is only done once */
if(init_ssl)
return 1;
init_ssl = TRUE; /* never again */
#ifdef USE_SSLEAY
return Curl_ossl_init();
#else
#ifdef USE_GNUTLS
return Curl_gtls_init();
#else
/* no SSL support */
return 1;
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}
/* Global cleanup */
void Curl_ssl_cleanup(void)
{
if(init_ssl) {
/* only cleanup if we did a previous init */
#ifdef USE_SSLEAY
Curl_ossl_cleanup();
#else
#ifdef USE_GNUTLS
Curl_gtls_cleanup();
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
init_ssl = FALSE;
}
}
CURLcode
Curl_ssl_connect(struct connectdata *conn, int sockindex)
{
#ifdef USE_SSL
/* mark this is being ssl enabled from here on. */
conn->ssl[sockindex].use = TRUE;
#ifdef USE_SSLEAY
return Curl_ossl_connect(conn, sockindex);
#else
#ifdef USE_GNUTLS
return Curl_gtls_connect(conn, sockindex);
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
#else
/* without SSL */
(void)conn;
(void)sockindex;
return CURLE_OK;
#endif /* USE_SSL */
}
#ifdef USE_SSL
/*
* Check if there's a session ID for the given connection in the cache, and if
* there's one suitable, it is provided. Returns TRUE when no entry matched.
*/
int Curl_ssl_getsessionid(struct connectdata *conn,
void **ssl_sessionid,
size_t *idsize) /* set 0 if unknown */
{
struct curl_ssl_session *check;
struct SessionHandle *data = conn->data;
long i;
for(i=0; i< data->set.ssl.numsessions; i++) {
check = &data->state.session[i];
if(!check->sessionid)
/* not session ID means blank entry */
continue;
if(curl_strequal(conn->host.name, check->name) &&
(conn->remote_port == check->remote_port) &&
Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
/* yes, we have a session ID! */
data->state.sessionage++; /* increase general age */
check->age = data->state.sessionage; /* set this as used in this age */
*ssl_sessionid = check->sessionid;
if(idsize)
*idsize = check->idsize;
return FALSE;
}
}
*ssl_sessionid = NULL;
return TRUE;
}
/*
* Kill a single session ID entry in the cache.
*/
static int kill_session(struct curl_ssl_session *session)
{
if(session->sessionid) {
/* defensive check */
/* free the ID the SSL-layer specific way */
#ifdef USE_SSLEAY
Curl_ossl_session_free(session->sessionid);
#else
Curl_gtls_session_free(session->sessionid);
#endif
session->sessionid=NULL;
session->age = 0; /* fresh */
Curl_free_ssl_config(&session->ssl_config);
Curl_safefree(session->name);
session->name = NULL; /* no name */
return 0; /* ok */
}
else
return 1;
}
/*
* Store session id in the session cache. The ID passed on to this function
* must already have been extracted and allocated the proper way for the SSL
* layer. Curl_XXXX_session_free() will be called to free/kill the session ID
* later on.
*/
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
void *ssl_sessionid,
size_t idsize)
{
int i;
struct SessionHandle *data=conn->data; /* the mother of all structs */
struct curl_ssl_session *store = &data->state.session[0];
long oldest_age=data->state.session[0].age; /* zero if unused */
char *clone_host;
clone_host = strdup(conn->host.name);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
/* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */
/* find an empty slot for us, or find the oldest */
for(i=1; (i<data->set.ssl.numsessions) &&
data->state.session[i].sessionid; i++) {
if(data->state.session[i].age < oldest_age) {
oldest_age = data->state.session[i].age;
store = &data->state.session[i];
}
}
if(i == data->set.ssl.numsessions)
/* cache is full, we must "kill" the oldest entry! */
kill_session(store);
else
store = &data->state.session[i]; /* use this slot */
/* now init the session struct wisely */
store->sessionid = ssl_sessionid;
store->idsize = idsize;
store->age = data->state.sessionage; /* set current age */
store->name = clone_host; /* clone host name */
store->remote_port = conn->remote_port; /* port number */
if (!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
#endif
void Curl_ssl_close_all(struct SessionHandle *data)
{
#ifdef USE_SSL
int i;
/* kill the session ID cache */
if(data->state.session) {
for(i=0; i< data->set.ssl.numsessions; i++)
/* the single-killer function handles empty table slots */
kill_session(&data->state.session[i]);
/* free the cache data */
free(data->state.session);
data->state.session = NULL;
}
#ifdef USE_SSLEAY
Curl_ossl_close_all(data);
#else
#ifdef USE_GNUTLS
Curl_gtls_close_all(data);
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
#else /* USE_SSL */
(void)data;
#endif /* USE_SSL */
}
void Curl_ssl_close(struct connectdata *conn)
{
if(conn->ssl[FIRSTSOCKET].use) {
#ifdef USE_SSLEAY
Curl_ossl_close(conn);
#else
#ifdef USE_GNUTLS
Curl_gtls_close(conn);
#else
(void)conn;
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}
}
/* Selects an (Open)SSL crypto engine
*/
CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
{
#ifdef USE_SSLEAY
return Curl_ossl_set_engine(data, engine);
#else
#ifdef USE_GNUTLS
/* FIX: add code here */
(void)data;
(void)engine;
return CURLE_FAILED_INIT;
#else
/* no SSL layer */
(void)data;
(void)engine;
return CURLE_FAILED_INIT;
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}
/* Selects an (Open?)SSL crypto engine
*/
CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
{
#ifdef USE_SSLEAY
return Curl_ossl_set_engine_default(data);
#else
#ifdef USE_GNUTLS
/* FIX: add code here */
(void)data;
return CURLE_FAILED_INIT;
#else
/* No SSL layer */
(void)data;
return CURLE_FAILED_INIT;
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}
/* Return list of OpenSSL crypto engine names. */
struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
{
#ifdef USE_SSLEAY
return Curl_ossl_engines_list(data);
#else
#ifdef USE_GNUTLS
/* FIX: add code here? */
(void)data;
return NULL;
#else
(void)data;
return NULL;
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}
/* return number of sent (non-SSL) bytes */
int Curl_ssl_send(struct connectdata *conn,
int sockindex,
void *mem,
size_t len)
{
#ifdef USE_SSLEAY
return Curl_ossl_send(conn, sockindex, mem, len);
#else
#ifdef USE_GNUTLS
return Curl_gtls_send(conn, sockindex, mem, len);
#else
(void)conn;
(void)sockindex;
(void)mem;
(void)len;
return 0;
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}
/* return number of received (decrypted) bytes */
/*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/
int Curl_ssl_recv(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
char *mem, /* store read data here */
size_t len) /* max amount to read */
{
#ifdef USE_SSL
ssize_t nread;
bool block = FALSE;
#ifdef USE_SSLEAY
nread = Curl_ossl_recv(conn, sockindex, mem, len, &block);
#else
#ifdef USE_GNUTLS
nread = Curl_gtls_recv(conn, sockindex, mem, len, &block);
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
if(nread == -1) {
infof(conn->data, "Curl_xxx_rcvs returned -1, block = %s\n",
block?"TRUE":"FALSE");
if(!block)
return 0; /* this is a true error, not EWOULDBLOCK */
else
return -1;
}
return nread;
#else /* USE_SSL */
(void)conn;
(void)sockindex;
(void)mem;
(void)len;
return 0;
#endif /* USE_SSL */
}
/*
* This sets up a session ID cache to the specified size. Make sure this code
* is agnostic to what underlying SSL technology we use.
*/
CURLcode Curl_ssl_initsessions(struct SessionHandle *data, long amount)
{
struct curl_ssl_session *session;
if(data->state.session)
/* this is just a precaution to prevent multiple inits */
return CURLE_OK;
session = (struct curl_ssl_session *)
malloc(amount * sizeof(struct curl_ssl_session));
if(!session)
return CURLE_OUT_OF_MEMORY;
/* "blank out" the newly allocated memory */
memset(session, 0, amount * sizeof(struct curl_ssl_session));
/* store the info in the SSL section */
data->set.ssl.numsessions = amount;
data->state.session = session;
data->state.sessionage = 1; /* this is brand new */
return CURLE_OK;
}
size_t Curl_ssl_version(char *buffer, size_t size)
{
#ifdef USE_SSLEAY
return Curl_ossl_version(buffer, size);
#else
#ifdef USE_GNUTLS
return Curl_gtls_version(buffer, size);
#else
(void)buffer;
(void)size;
return 0; /* no SSL support */
#endif /* USE_GNUTLS */
#endif /* USE_SSLEAY */
}

72
lib/sslgen.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef __SSLGEN_H
#define __SSLGEN_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
bool Curl_ssl_config_matches(struct ssl_config_data* data,
struct ssl_config_data* needle);
bool Curl_clone_ssl_config(struct ssl_config_data* source,
struct ssl_config_data* dest);
void Curl_free_ssl_config(struct ssl_config_data* sslc);
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex);
void Curl_ssl_close(struct connectdata *conn);
/* tell the SSL stuff to close down all open information regarding
connections (and thus session ID caching etc) */
void Curl_ssl_close_all(struct SessionHandle *data);
CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data);
int Curl_ssl_send(struct connectdata *conn,
int sockindex,
void *mem,
size_t len);
int Curl_ssl_recv(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
char *mem, /* store read data here */
size_t len); /* max amount to read */
/* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct SessionHandle *, long);
/* extract a session ID */
int Curl_ssl_getsessionid(struct connectdata *conn,
void **ssl_sessionid,
size_t *idsize) /* set 0 if unknown */;
/* add a new session ID */
CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
void *ssl_sessionid,
size_t idsize);
struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data);
size_t Curl_ssl_version(char *buffer, size_t size);
#if !defined(USE_SSL) && !defined(SSLGEN_C)
/* set up blank macros for none-SSL builds */
#define Curl_ssl_close_all(x)
#endif
#endif

View File

@@ -22,8 +22,13 @@
***************************************************************************/
/*
* The original SSL code for curl was written by
* Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
* Source file for all OpenSSL-specific code for the TLS/SSL layer. No code
* but sslgen.c should ever call or use these functions.
*/
/*
* The original SSLeay-using code for curl was written by Linas Vepstas and
* Sampo Kellomaki 1998.
*/
#include "setup.h"
@@ -47,6 +52,7 @@
#include "connect.h" /* Curl_ourerrno() proto */
#include "strequal.h"
#include "select.h"
#include "sslgen.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
@@ -447,8 +453,8 @@ int cert_stuff(struct connectdata *conn,
#endif
case SSL_FILETYPE_PKCS12:
if(!cert_done) {
failf(data, "file type P12 for private key not supported\n");
return 0;
failf(data, "file type P12 for private key not supported\n");
return 0;
}
break;
default:
@@ -519,27 +525,20 @@ static char *SSL_strerror(unsigned long error, char *buf, size_t size)
return (buf);
}
/* "global" init done? */
static int init_ssl=0;
/* we have the "SSL is seeded" boolean global for the application to
prevent multiple time-consuming seedings in vain */
static bool ssl_seeded = FALSE;
#endif /* USE_SSLEAY */
#ifdef USE_SSLEAY
/**
* Global SSL init
*
* @retval 0 error initializing SSL
* @retval 1 SSL initialized successfully
*/
int Curl_SSL_init(void)
int Curl_ossl_init(void)
{
#ifdef USE_SSLEAY
/* make sure this is only done once */
if(init_ssl)
return 1;
#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
ENGINE_load_builtin_engines();
#endif
@@ -551,57 +550,39 @@ int Curl_SSL_init(void)
if (!SSLeay_add_ssl_algorithms())
return 0;
init_ssl++; /* never again */
#else
/* SSL disabled, do nothing */
#endif
return 1;
}
/* Global cleanup */
void Curl_SSL_cleanup(void)
{
#endif /* USE_SSLEAY */
#ifdef USE_SSLEAY
if(init_ssl) {
/* only cleanup if we did a previous init */
/* Free the SSL error strings */
ERR_free_strings();
/* Global cleanup */
void Curl_ossl_cleanup(void)
{
/* Free the SSL error strings */
ERR_free_strings();
/* EVP_cleanup() removes all ciphers and digests from the
table. */
EVP_cleanup();
/* EVP_cleanup() removes all ciphers and digests from the
table. */
EVP_cleanup();
#ifdef HAVE_ENGINE_cleanup
ENGINE_cleanup();
ENGINE_cleanup();
#endif
#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
/* this function was not present in 0.9.6b, but was added sometimes
later */
CRYPTO_cleanup_all_ex_data();
#endif
init_ssl=0; /* not inited any more */
}
#else
/* SSL disabled, do nothing */
/* this function was not present in 0.9.6b, but was added sometimes
later */
CRYPTO_cleanup_all_ex_data();
#endif
}
#ifndef USE_SSLEAY
void Curl_SSL_Close(struct connectdata *conn)
{
(void)conn;
}
#endif
#endif /* USE_SSLEAY */
/* Selects an OpenSSL crypto engine
*/
CURLcode Curl_SSL_set_engine(struct SessionHandle *data, const char *engine)
CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine)
{
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
ENGINE *e = ENGINE_by_id(engine);
@@ -633,11 +614,12 @@ CURLcode Curl_SSL_set_engine(struct SessionHandle *data, const char *engine)
#endif
}
/* Sets above engine as default for all SSL operations
#ifdef USE_SSLEAY
/* Sets engine as default for all SSL operations
*/
CURLcode Curl_SSL_set_engine_default(struct SessionHandle *data)
CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data)
{
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
#ifdef HAVE_OPENSSL_ENGINE_H
if (data->state.engine) {
if (ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
infof(data,"set default crypto engine %s\n", data->state.engine);
@@ -650,12 +632,13 @@ CURLcode Curl_SSL_set_engine_default(struct SessionHandle *data)
#else
(void) data;
#endif
return (CURLE_OK);
return CURLE_OK;
}
#endif /* USE_SSLEAY */
/* Return list of OpenSSL crypto engine names.
*/
struct curl_slist *Curl_SSL_engines_list(struct SessionHandle *data)
struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data)
{
struct curl_slist *list = NULL;
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
@@ -674,217 +657,62 @@ struct curl_slist *Curl_SSL_engines_list(struct SessionHandle *data)
/*
* This function is called when an SSL connection is closed.
*/
void Curl_SSL_Close(struct connectdata *conn)
void Curl_ossl_close(struct connectdata *conn)
{
if(conn->ssl[FIRSTSOCKET].use) {
int i;
/*
ERR_remove_state() frees the error queue associated with
thread pid. If pid == 0, the current thread will have its
error queue removed.
int i;
/*
ERR_remove_state() frees the error queue associated with
thread pid. If pid == 0, the current thread will have its
error queue removed.
Since error queue data structures are allocated
automatically for new threads, they must be freed when
threads are terminated in oder to avoid memory leaks.
*/
ERR_remove_state(0);
Since error queue data structures are allocated
automatically for new threads, they must be freed when
threads are terminated in oder to avoid memory leaks.
*/
ERR_remove_state(0);
for(i=0; i<2; i++) {
struct ssl_connect_data *connssl = &conn->ssl[i];
for(i=0; i<2; i++) {
struct ssl_connect_data *connssl = &conn->ssl[i];
if(connssl->handle) {
(void)SSL_shutdown(connssl->handle);
SSL_set_connect_state(connssl->handle);
if(connssl->handle) {
(void)SSL_shutdown(connssl->handle);
SSL_set_connect_state(connssl->handle);
SSL_free (connssl->handle);
connssl->handle = NULL;
}
if(connssl->ctx) {
SSL_CTX_free (connssl->ctx);
connssl->ctx = NULL;
}
connssl->use = FALSE; /* get back to ordinary socket usage */
SSL_free (connssl->handle);
connssl->handle = NULL;
}
}
}
/*
* This sets up a session cache to the specified size.
*/
CURLcode Curl_SSL_InitSessions(struct SessionHandle *data, long amount)
{
struct curl_ssl_session *session;
if(data->state.session)
/* this is just a precaution to prevent multiple inits */
return CURLE_OK;
session = (struct curl_ssl_session *)
malloc(amount * sizeof(struct curl_ssl_session));
if(!session)
return CURLE_OUT_OF_MEMORY;
/* "blank out" the newly allocated memory */
memset(session, 0, amount * sizeof(struct curl_ssl_session));
/* store the info in the SSL section */
data->set.ssl.numsessions = amount;
data->state.session = session;
data->state.sessionage = 1; /* this is brand new */
return CURLE_OK;
}
/*
* Check if there's a session ID for the given connection in the cache,
* and if there's one suitable, it is returned.
*/
static int Get_SSL_Session(struct connectdata *conn,
SSL_SESSION **ssl_sessionid)
{
struct curl_ssl_session *check;
struct SessionHandle *data = conn->data;
long i;
for(i=0; i< data->set.ssl.numsessions; i++) {
check = &data->state.session[i];
if(!check->sessionid)
/* not session ID means blank entry */
continue;
if(curl_strequal(conn->host.name, check->name) &&
(conn->remote_port == check->remote_port) &&
Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
/* yes, we have a session ID! */
data->state.sessionage++; /* increase general age */
check->age = data->state.sessionage; /* set this as used in this age */
*ssl_sessionid = check->sessionid;
return FALSE;
if(connssl->ctx) {
SSL_CTX_free (connssl->ctx);
connssl->ctx = NULL;
}
connssl->use = FALSE; /* get back to ordinary socket usage */
}
*ssl_sessionid = (SSL_SESSION *)NULL;
return TRUE;
}
/*
* Kill a single session ID entry in the cache.
*/
static int Kill_Single_Session(struct curl_ssl_session *session)
void Curl_ossl_session_free(void *ptr)
{
if(session->sessionid) {
/* defensive check */
/* free the ID */
SSL_SESSION_free(session->sessionid);
session->sessionid=NULL;
session->age = 0; /* fresh */
Curl_free_ssl_config(&session->ssl_config);
Curl_safefree(session->name);
session->name = NULL; /* no name */
return 0; /* ok */
}
else
return 1;
/* free the ID */
SSL_SESSION_free(ptr);
}
/*
* This function is called when the 'data' struct is going away. Close
* down everything and free all resources!
*/
int Curl_SSL_Close_All(struct SessionHandle *data)
int Curl_ossl_close_all(struct SessionHandle *data)
{
int i;
if(data->state.session) {
for(i=0; i< data->set.ssl.numsessions; i++)
/* the single-killer function handles empty table slots */
Kill_Single_Session(&data->state.session[i]);
/* free the cache data */
free(data->state.session);
data->state.session = NULL;
}
#ifdef HAVE_OPENSSL_ENGINE_H
if(data->state.engine) {
ENGINE_finish(data->state.engine);
ENGINE_free(data->state.engine);
data->state.engine = NULL;
}
#else
(void)data;
#endif
return 0;
}
/*
* Extract the session id and store it in the session cache.
*/
static CURLcode Store_SSL_Session(struct connectdata *conn,
struct ssl_connect_data *ssl)
{
SSL_SESSION *ssl_sessionid;
int i;
struct SessionHandle *data=conn->data; /* the mother of all structs */
struct curl_ssl_session *store = &data->state.session[0];
long oldest_age=data->state.session[0].age; /* zero if unused */
char *clone_host;
clone_host = strdup(conn->host.name);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
/* ask OpenSSL, say please */
#ifdef HAVE_SSL_GET1_SESSION
ssl_sessionid = SSL_get1_session(ssl->handle);
/* SSL_get1_session() will increment the reference
count and the session will stay in memory until explicitly freed with
SSL_SESSION_free(3), regardless of its state.
This function was introduced in openssl 0.9.5a. */
#else
ssl_sessionid = SSL_get_session(ssl->handle);
/* if SSL_get1_session() is unavailable, use SSL_get_session().
This is an inferior option because the session can be flushed
at any time by openssl. It is included only so curl compiles
under versions of openssl < 0.9.5a.
WARNING: How curl behaves if it's session is flushed is
untested.
*/
#endif
/* Now we should add the session ID and the host name to the cache, (remove
the oldest if necessary) */
/* find an empty slot for us, or find the oldest */
for(i=1; (i<data->set.ssl.numsessions) &&
data->state.session[i].sessionid; i++) {
if(data->state.session[i].age < oldest_age) {
oldest_age = data->state.session[i].age;
store = &data->state.session[i];
}
}
if(i == data->set.ssl.numsessions)
/* cache is full, we must "kill" the oldest entry! */
Kill_Single_Session(store);
else
store = &data->state.session[i]; /* use this slot */
/* now init the session struct wisely */
store->sessionid = ssl_sessionid;
store->age = data->state.sessionage; /* set current age */
store->name = clone_host; /* clone host name */
store->remote_port = conn->remote_port; /* port number */
if (!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
const char *prefix,
ASN1_UTCTIME *tm)
@@ -1280,28 +1108,25 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
}
#endif
#ifdef USE_SSLEAY
/* ====================================================== */
CURLcode
Curl_SSLConnect(struct connectdata *conn,
int sockindex)
Curl_ossl_connect(struct connectdata *conn,
int sockindex)
{
CURLcode retcode = CURLE_OK;
#ifdef USE_SSLEAY
struct SessionHandle *data = conn->data;
int err;
long lerr;
int what;
char * str;
SSL_METHOD *req_method;
SSL_SESSION *ssl_sessionid=NULL;
void *ssl_sessionid=NULL;
ASN1_TIME *certdate;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* mark this is being ssl enabled from here on out. */
connssl->use = TRUE;
if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
/* Make funny stuff to get random input */
random_the_seed(data);
@@ -1447,19 +1272,16 @@ Curl_SSLConnect(struct connectdata *conn,
connssl->server_cert = 0x0;
if(!conn->bits.reuse) {
/* We're not re-using a connection, check if there's a cached ID we
can/should use here! */
if(!Get_SSL_Session(conn, &ssl_sessionid)) {
/* we got a session id, use it! */
if (!SSL_set_session(connssl->handle, ssl_sessionid)) {
failf(data, "SSL: SSL_set_session failed: %s",
ERR_error_string(ERR_get_error(),NULL));
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
infof (data, "SSL re-using session ID\n");
/* Check if there's a cached ID we can/should use here! */
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
/* we got a session id, use it! */
if (!SSL_set_session(connssl->handle, ssl_sessionid)) {
failf(data, "SSL: SSL_set_session failed: %s",
ERR_error_string(ERR_get_error(),NULL));
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
infof (data, "SSL re-using session ID\n");
}
/* pass the raw socket into the SSL layers */
@@ -1473,16 +1295,13 @@ Curl_SSLConnect(struct connectdata *conn,
int writefd;
int readfd;
long timeout_ms;
long has_passed;
/* Find out if any timeout is set. If not, use 300 seconds.
Otherwise, figure out the most strict timeout of the two possible one
and then how much time that has elapsed to know how much time we
allow for the connect call */
if(data->set.timeout || data->set.connecttimeout) {
long has_passed;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
/* get the most strict timeout of the ones converted to milliseconds */
if(data->set.timeout &&
@@ -1490,20 +1309,22 @@ Curl_SSLConnect(struct connectdata *conn,
timeout_ms = data->set.timeout*1000;
else
timeout_ms = data->set.connecttimeout*1000;
/* subtract the passed time */
timeout_ms -= has_passed;
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEOUTED;
}
}
else
/* no particular time-out has been set */
timeout_ms= DEFAULT_CONNECT_TIMEOUT;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
/* subtract the passed time */
timeout_ms -= has_passed;
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEOUTED;
}
readfd = CURL_SOCKET_BAD;
writefd = CURL_SOCKET_BAD;
@@ -1586,12 +1407,7 @@ Curl_SSLConnect(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
else {
#if !defined(WIN32) && defined(EINTR)
/* For platforms without EINTR all errnos are bad */
if (errno == EINTR)
continue; /* retry the select() */
#endif
/* anything other than the unimportant EINTR is fatally bad */
/* anything that gets here is fatally bad */
failf(data, "select on SSL socket, errno: %d", Curl_ourerrno());
return CURLE_SSL_CONNECT_ERROR;
}
@@ -1605,9 +1421,30 @@ Curl_SSLConnect(struct connectdata *conn,
if(!ssl_sessionid) {
/* Since this is not a cached session ID, then we want to stach this one
in the cache! */
retcode = Store_SSL_Session(conn, connssl);
SSL_SESSION *ssl_sessionid;
#ifdef HAVE_SSL_GET1_SESSION
ssl_sessionid = SSL_get1_session(connssl->handle);
/* SSL_get1_session() will increment the reference
count and the session will stay in memory until explicitly freed with
SSL_SESSION_free(3), regardless of its state.
This function was introduced in openssl 0.9.5a. */
#else
ssl_sessionid = SSL_get_session(connssl->handle);
/* if SSL_get1_session() is unavailable, use SSL_get_session().
This is an inferior option because the session can be flushed
at any time by openssl. It is included only so curl compiles
under versions of openssl < 0.9.5a.
WARNING: How curl behaves if it's session is flushed is
untested.
*/
#endif
retcode = Curl_ssl_addsessionid(conn, ssl_sessionid,
0 /* unknown size */);
if(retcode) {
failf(data,"failure to store ssl session");
failf(data, "failed to store ssl session");
return retcode;
}
}
@@ -1686,9 +1523,145 @@ Curl_SSLConnect(struct connectdata *conn,
X509_free(connssl->server_cert);
connssl->server_cert = NULL;
#else /* USE_SSLEAY */
(void)conn;
(void)sockindex;
#endif
return retcode;
}
/* return number of sent (non-SSL) bytes */
int Curl_ossl_send(struct connectdata *conn,
int sockindex,
void *mem,
size_t len)
{
/* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */
int err;
char error_buffer[120]; /* OpenSSL documents that this must be at least 120
bytes long. */
unsigned long sslerror;
int rc = SSL_write(conn->ssl[sockindex].handle, mem, (int)len);
if(rc < 0) {
err = SSL_get_error(conn->ssl[sockindex].handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* The operation did not complete; the same TLS/SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
return 0;
case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
Curl_ourerrno());
return -1;
case SSL_ERROR_SSL:
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
sslerror = ERR_get_error();
failf(conn->data, "SSL_write() error: %s\n",
ERR_error_string(sslerror, error_buffer));
return -1;
}
/* a true error */
failf(conn->data, "SSL_write() return error %d\n", err);
return -1;
}
return rc; /* number of bytes */
}
/*
* If the read would block we return -1 and set 'wouldblock' to TRUE.
* Otherwise we return the amount of data read. Other errors should return -1
* and set 'wouldblock' to FALSE.
*/
ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool *wouldblock)
{
char error_buffer[120]; /* OpenSSL documents that this must be at
least 120 bytes long. */
unsigned long sslerror;
ssize_t nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf,
(int)buffersize);
*wouldblock = FALSE;
if(nread < 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
case SSL_ERROR_ZERO_RETURN: /* no more data */
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */
*wouldblock = TRUE;
return -1; /* basically EWOULDBLOCK */
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
sslerror = ERR_get_error();
failf(conn->data, "SSL read: %s, errno %d",
ERR_error_string(sslerror, error_buffer),
Curl_ourerrno() );
return -1;
}
}
return nread;
}
size_t Curl_ossl_version(char *buffer, size_t size)
{
#if (SSLEAY_VERSION_NUMBER >= 0x905000)
{
char sub[2];
unsigned long ssleay_value;
sub[1]='\0';
ssleay_value=SSLeay();
if(ssleay_value < 0x906000) {
ssleay_value=SSLEAY_VERSION_NUMBER;
sub[0]='\0';
}
else {
if(ssleay_value&0xff0) {
sub[0]=(char)((ssleay_value>>4)&0xff) + 'a' -1;
}
else
sub[0]='\0';
}
return snprintf(buffer, size, " OpenSSL/%lx.%lx.%lx%s",
(ssleay_value>>28)&0xf,
(ssleay_value>>20)&0xff,
(ssleay_value>>12)&0xff,
sub);
}
#else /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */
#if (SSLEAY_VERSION_NUMBER >= 0x900000)
return snprintf(buffer, size, " OpenSSL/%lx.%lx.%lx",
(SSLEAY_VERSION_NUMBER>>28)&0xff,
(SSLEAY_VERSION_NUMBER>>20)&0xff,
(SSLEAY_VERSION_NUMBER>>12)&0xf);
#else /* (SSLEAY_VERSION_NUMBER >= 0x900000) */
{
char sub[2];
sub[1]='\0';
if(SSLEAY_VERSION_NUMBER&0x0f) {
sub[0]=(SSLEAY_VERSION_NUMBER&0x0f) + 'a' -1;
}
else
sub[0]='\0';
return snprintf(buffer, size, " SSL/%x.%x.%x%s",
(SSLEAY_VERSION_NUMBER>>12)&0xff,
(SSLEAY_VERSION_NUMBER>>8)&0xf,
(SSLEAY_VERSION_NUMBER>>4)&0xf, sub);
}
#endif /* (SSLEAY_VERSION_NUMBER >= 0x900000) */
#endif /* SSLEAY_VERSION_NUMBER is less than 0.9.5 */
}
#endif /* USE_SSLEAY */

View File

@@ -22,27 +22,43 @@
*
* $Id$
***************************************************************************/
/*
* This header should only be needed to get included by sslgen.c and ssluse.c
*/
#include "urldata.h"
CURLcode Curl_SSLConnect(struct connectdata *conn, int sockindex);
int Curl_SSL_init(void); /* Global SSL init */
void Curl_SSL_cleanup(void); /* Global SSL cleanup */
/* init the SSL session ID cache */
CURLcode Curl_SSL_InitSessions(struct SessionHandle *, long);
void Curl_SSL_Close(struct connectdata *conn); /* close a SSL connection */
/* tell the SSL stuff to close down all open information regarding
connections (and thus session ID caching etc) */
int Curl_SSL_Close_All(struct SessionHandle *data);
CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
void Curl_ossl_close(struct connectdata *conn); /* close a SSL connection */
/* tell OpenSSL to close down all open information regarding connections (and
thus session ID caching etc) */
int Curl_ossl_close_all(struct SessionHandle *data);
/* Sets an OpenSSL engine */
CURLcode Curl_SSL_set_engine(struct SessionHandle *data, const char *engine);
CURLcode Curl_ossl_set_engine(struct SessionHandle *data, const char *engine);
/* Sets above engine as default for all SSL operations */
CURLcode Curl_SSL_set_engine_default(struct SessionHandle *data);
/* function provided for the generic SSL-layer, called when a session id
should be freed */
void Curl_ossl_session_free(void *ptr);
/* Sets engine as default for all SSL operations */
CURLcode Curl_ossl_set_engine_default(struct SessionHandle *data);
/* Build list of OpenSSL engines */
struct curl_slist *Curl_SSL_engines_list(struct SessionHandle *data);
struct curl_slist *Curl_ossl_engines_list(struct SessionHandle *data);
int Curl_ossl_init(void);
void Curl_ossl_cleanup(void);
int Curl_ossl_send(struct connectdata *conn,
int sockindex,
void *mem,
size_t len);
ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool *wouldblock);
size_t Curl_ossl_version(char *buffer, size_t size);
#endif

View File

@@ -25,14 +25,6 @@
#include <curl/curl.h>
#if 0
/*
* These two actually are public functions, which are in <curl/curl.h>
*/
int curl_strequal(const char *first, const char *second);
int curl_strnequal(const char *first, const char *second, size_t max);
#endif
#define strequal(a,b) curl_strequal(a,b)
#define strnequal(a,b,c) curl_strnequal(a,b,c)
@@ -45,7 +37,7 @@ char *Curl_strcasestr(const char *haystack, const char *needle);
#ifndef HAVE_STRLCAT
#define strlcat(x,y,z) Curl_strlcat(x,y,z)
size_t Curl_strlcat(char *dst, const char *src, size_t siz);
#endif
size_t strlcat(char *dst, const char *src, size_t siz);
#endif

View File

@@ -94,7 +94,7 @@
#include "http.h"
#include "url.h"
#include "getinfo.h"
#include "ssluse.h"
#include "sslgen.h"
#include "http_digest.h"
#include "http_ntlm.h"
#include "http_negotiate.h"
@@ -243,6 +243,7 @@ CURLcode Curl_readrewind(struct connectdata *conn)
}
#ifdef USE_SSLEAY
/* FIX: this is nasty OpenSSL-specific code that really shouldn't be here */
static int data_pending(struct connectdata *conn)
{
if(conn->ssl[FIRSTSOCKET].handle)
@@ -696,6 +697,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
* fields. */
conn->size=0;
conn->maxdownload=0;
k->ignorecl = TRUE; /* ignore Content-Length headers */
break;
default:
/* nothing */
@@ -712,7 +714,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
the header completely if we get a 416 response as then we're
resuming a document that we don't get, and this header contains
info about the true size of the document we didn't get now. */
if ((k->httpcode != 416) &&
if (!k->ignorecl &&
checkprefix("Content-Length:", k->p)) {
contentlength = curlx_strtoofft(k->p+15, NULL, 10);
if (data->set.max_filesize &&
@@ -1597,20 +1599,17 @@ Transfer(struct connectdata *conn)
*/
CURLcode Curl_pretransfer(struct SessionHandle *data)
{
CURLcode res;
if(!data->change.url)
/* we can't do anything wihout URL */
return CURLE_URL_MALFORMAT;
#ifdef USE_SSLEAY
{
/* Init the SSL session ID cache here. We do it here since we want to do
it after the *_setopt() calls (that could change the size of the cache)
but before any transfer takes place. */
CURLcode res = Curl_SSL_InitSessions(data, data->set.ssl.numsessions);
if(res)
return res;
}
#endif
/* Init the SSL session ID cache here. We do it here since we want to do it
after the *_setopt() calls (that could change the size of the cache) but
before any transfer takes place. */
res = Curl_ssl_initsessions(data, data->set.ssl.numsessions);
if(res)
return res;
data->set.followlocation=0; /* reset the location-follow counter */
data->state.this_is_a_follow = FALSE; /* reset this */

120
lib/url.c
View File

@@ -102,7 +102,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
#include "formdata.h"
#include "base64.h"
#include "ssluse.h"
#include "sslgen.h"
#include "hostip.h"
#include "transfer.h"
#include "sendf.h"
@@ -154,7 +154,6 @@ static bool ConnectionExists(struct SessionHandle *data,
struct connectdata **usethis);
static long ConnectionStore(struct SessionHandle *data,
struct connectdata *conn);
static bool safe_strequal(char* str1, char* str2);
#ifndef USE_ARES
/* not for Win32, unless it is cygwin
@@ -211,11 +210,8 @@ CURLcode Curl_close(struct SessionHandle *data)
}
}
#ifdef USE_SSLEAY
/* Close down all open SSL info and sessions */
Curl_SSL_Close_All(data);
#endif
Curl_ssl_close_all(data);
Curl_safefree(data->state.first_host);
Curl_safefree(data->state.scratch);
@@ -832,7 +828,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
#if ! defined(USE_SSLEAY) && !defined(USE_WINDOWS_SSPI)
#ifndef USE_NTLM
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
@@ -852,7 +848,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
#ifndef USE_SSLEAY
#ifndef USE_NTLM
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
@@ -1153,14 +1149,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
*/
argptr = va_arg(param, char *);
if (argptr && argptr[0])
result = Curl_SSL_set_engine(data, argptr);
result = Curl_ssl_set_engine(data, argptr);
break;
case CURLOPT_SSLENGINE_DEFAULT:
/*
* flag to set engine as default.
*/
result = Curl_SSL_set_engine_default(data);
result = Curl_ssl_set_engine_default(data);
break;
case CURLOPT_CRLF:
/*
@@ -1450,9 +1446,7 @@ CURLcode Curl_disconnect(struct connectdata *conn)
data->state.authproblem = FALSE;
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
Curl_ntlm_cleanup(conn);
#endif
}
if(conn->curl_disconnect)
@@ -1481,7 +1475,7 @@ CURLcode Curl_disconnect(struct connectdata *conn)
freed with idn_free() since this was
allocated by libidn */
#endif
Curl_SSL_Close(conn);
Curl_ssl_close(conn);
/* close possibly still open sockets */
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
@@ -2419,10 +2413,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(checkprefix("GOPHER.", conn->host.name))
strcpy(conn->protostr, "gopher");
#ifdef USE_SSLEAY
#ifdef USE_SSL
else if(checkprefix("FTPS", conn->host.name))
strcpy(conn->protostr, "ftps");
#endif /* USE_SSLEAY */
#endif /* USE_SSL */
else if(checkprefix("FTP.", conn->host.name))
strcpy(conn->protostr, "ftp");
else if(checkprefix("TELNET.", conn->host.name))
@@ -2728,7 +2722,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#endif
}
else if (strequal(conn->protostr, "HTTPS")) {
#if defined(USE_SSLEAY) && !defined(CURL_DISABLE_HTTP)
#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
conn->port = (data->set.use_port && data->state.allow_port)?
data->set.use_port:PORT_HTTPS;
@@ -2740,11 +2734,11 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->curl_done = Curl_http_done;
conn->curl_connect = Curl_http_connect;
#else /* USE_SSLEAY */
#else /* USE_SS */
failf(data, LIBCURL_NAME
" was built with SSL disabled, https: not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif /* !USE_SSLEAY */
#endif /* !USE_SSL */
}
else if (strequal(conn->protostr, "GOPHER")) {
#ifndef CURL_DISABLE_GOPHER
@@ -2774,7 +2768,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
int port = PORT_FTP;
if(strequal(conn->protostr, "FTPS")) {
#ifdef USE_SSLEAY
#ifdef USE_SSL
conn->protocol |= PROT_FTPS|PROT_SSL;
conn->ssl[SECONDARYSOCKET].use = TRUE; /* send data securely */
port = PORT_FTPS;
@@ -2782,7 +2776,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
failf(data, LIBCURL_NAME
" was built with SSL disabled, ftps: not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif /* !USE_SSLEAY */
#endif /* !USE_SSL */
}
conn->port = (data->set.use_port && data->state.allow_port)?
@@ -3739,89 +3733,3 @@ CURLcode Curl_do_more(struct connectdata *conn)
return result;
}
static bool safe_strequal(char* str1, char* str2)
{
if(str1 && str2)
/* both pointers point to something then compare them */
return strequal(str1, str2);
else
/* if both pointers are NULL then treat them as equal */
return (!str1 && !str2);
}
bool
Curl_ssl_config_matches(struct ssl_config_data* data,
struct ssl_config_data* needle)
{
if((data->version == needle->version) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
safe_strequal(data->CApath, needle->CApath) &&
safe_strequal(data->CAfile, needle->CAfile) &&
safe_strequal(data->random_file, needle->random_file) &&
safe_strequal(data->egdsocket, needle->egdsocket) &&
safe_strequal(data->cipher_list, needle->cipher_list))
return TRUE;
return FALSE;
}
bool
Curl_clone_ssl_config(struct ssl_config_data *source,
struct ssl_config_data *dest)
{
dest->verifyhost = source->verifyhost;
dest->verifypeer = source->verifypeer;
dest->version = source->version;
if(source->CAfile) {
dest->CAfile = strdup(source->CAfile);
if(!dest->CAfile)
return FALSE;
}
if(source->CApath) {
dest->CApath = strdup(source->CApath);
if(!dest->CApath)
return FALSE;
}
if(source->cipher_list) {
dest->cipher_list = strdup(source->cipher_list);
if(!dest->cipher_list)
return FALSE;
}
if(source->egdsocket) {
dest->egdsocket = strdup(source->egdsocket);
if(!dest->egdsocket)
return FALSE;
}
if(source->random_file) {
dest->random_file = strdup(source->random_file);
if(!dest->random_file)
return FALSE;
}
return TRUE;
}
void Curl_free_ssl_config(struct ssl_config_data* sslc)
{
if(sslc->CAfile)
free(sslc->CAfile);
if(sslc->CApath)
free(sslc->CApath);
if(sslc->cipher_list)
free(sslc->cipher_list);
if(sslc->egdsocket)
free(sslc->egdsocket);
if(sslc->random_file)
free(sslc->random_file);
}

View File

@@ -41,11 +41,6 @@ CURLcode Curl_disconnect(struct connectdata *);
CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
bool Curl_ssl_config_matches(struct ssl_config_data* data,
struct ssl_config_data* needle);
bool Curl_clone_ssl_config(struct ssl_config_data* source,
struct ssl_config_data* dest);
void Curl_free_ssl_config(struct ssl_config_data* sslc);
void Curl_safefree(void *ptr);
CURLcode Curl_protocol_fdset(struct connectdata *conn,
fd_set *read_fd_set,

View File

@@ -50,7 +50,6 @@
#include "formdata.h"
#ifdef USE_SSLEAY
/* SSLeay stuff usually in /usr/local/ssl/include */
#ifdef USE_OPENSSL
#include "openssl/rsa.h"
#include "openssl/crypto.h"
@@ -64,14 +63,18 @@
#ifdef HAVE_OPENSSL_PKCS12_H
#include <openssl/pkcs12.h>
#endif
#else
#else /* SSLeay-style includes */
#include "rsa.h"
#include "crypto.h"
#include "x509.h"
#include "pem.h"
#include "ssl.h"
#include "err.h"
#endif
#endif /* USE_OPENSSL */
#endif /* USE_SSLEAY */
#ifdef USE_GNUTLS
#include <gnutls/gnutls.h>
#endif
#ifdef HAVE_NETINET_IN_H
@@ -139,6 +142,10 @@ struct ssl_connect_data {
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
#ifdef USE_GNUTLS
gnutls_session session;
gnutls_anon_client_credentials cred;
#endif /* USE_GNUTLS */
};
struct ssl_config_data {
@@ -162,6 +169,7 @@ struct ssl_config_data {
struct curl_ssl_session {
char *name; /* host name for which this ID was used */
void *sessionid; /* as returned from the SSL layer */
size_t idsize; /* if known, otherwise 0 */
long age; /* just a number, the higher the more recent */
unsigned short remote_port; /* remote port to connect to */
struct ssl_config_data ssl_config; /* setup for this session */
@@ -486,6 +494,8 @@ struct Curl_transfer_keeper {
and we're uploading the last chunk */
bool ignorebody; /* we read a response-body but we ignore it! */
bool ignorecl; /* This HTTP response has no body so we ignore the Content-
Length: header */
};
#if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) || \
@@ -659,20 +669,16 @@ struct connectdata {
char *newurl; /* This can only be set if a Location: was in the
document headers */
int sec_complete; /* if krb4 is enabled for this connection */
#ifdef HAVE_KRB4
enum protection_level command_prot;
enum protection_level data_prot;
enum protection_level request_data_prot;
size_t buffer_size;
struct krb4buffer in_buffer, out_buffer;
int sec_complete;
void *app_data;
const struct Curl_sec_client_mech *mech;
struct sockaddr_in local_addr;
#endif
/*************** Request - specific items ************/

View File

@@ -28,6 +28,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "sslgen.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
@@ -40,87 +41,20 @@
#include <stringprep.h>
#endif
#ifdef USE_SSLEAY
static int getssl_version(char *ptr, size_t left, long *num)
{
#if (SSLEAY_VERSION_NUMBER >= 0x905000)
{
char sub[2];
unsigned long ssleay_value;
sub[1]='\0';
ssleay_value=SSLeay();
*num = (long)ssleay_value;
if(ssleay_value < 0x906000) {
ssleay_value=SSLEAY_VERSION_NUMBER;
sub[0]='\0';
}
else {
if(ssleay_value&0xff0) {
sub[0]=(char)((ssleay_value>>4)&0xff) + 'a' -1;
}
else
sub[0]='\0';
}
return snprintf(ptr, left, " OpenSSL/%lx.%lx.%lx%s",
(ssleay_value>>28)&0xf,
(ssleay_value>>20)&0xff,
(ssleay_value>>12)&0xff,
sub);
}
#else
*num = SSLEAY_VERSION_NUMBER;
#if (SSLEAY_VERSION_NUMBER >= 0x900000)
return snprintf(ptr, left, " OpenSSL/%lx.%lx.%lx",
(SSLEAY_VERSION_NUMBER>>28)&0xff,
(SSLEAY_VERSION_NUMBER>>20)&0xff,
(SSLEAY_VERSION_NUMBER>>12)&0xf);
#else
{
char sub[2];
sub[1]='\0';
if(SSLEAY_VERSION_NUMBER&0x0f) {
sub[0]=(SSLEAY_VERSION_NUMBER&0x0f) + 'a' -1;
}
else
sub[0]='\0';
return snprintf(ptr, left, " SSL/%x.%x.%x%s",
(SSLEAY_VERSION_NUMBER>>12)&0xff,
(SSLEAY_VERSION_NUMBER>>8)&0xf,
(SSLEAY_VERSION_NUMBER>>4)&0xf, sub);
}
#endif
#endif
}
#endif
char *curl_version(void)
{
static char version[200];
char *ptr=version;
/* to prevent compier warnings, we only declare len if we have code
that uses it */
#if defined(USE_SSLEAY) || defined(HAVE_LIBZ) || defined(USE_ARES) || \
defined(USE_LIBIDN)
int len;
#endif
size_t len;
size_t left = sizeof(version);
strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION );
ptr=strchr(ptr, '\0');
left -= strlen(ptr);
#ifdef USE_SSLEAY
{
long num;
len = getssl_version(ptr, left, &num);
left -= len;
ptr += len;
}
#endif
len = Curl_ssl_version(ptr, left);
left -= len;
ptr += len;
#ifdef HAVE_LIBZ
len = snprintf(ptr, left, " zlib/%s", zlibVersion());
@@ -169,7 +103,7 @@ static const char * const protocols[] = {
"file",
#endif
#ifdef USE_SSLEAY
#ifdef USE_SSL
#ifndef CURL_DISABLE_HTTP
"https",
#endif
@@ -192,10 +126,10 @@ static curl_version_info_data version_info = {
#ifdef HAVE_KRB4
| CURL_VERSION_KERBEROS4
#endif
#ifdef USE_SSLEAY
#ifdef USE_SSL
| CURL_VERSION_SSL
#endif
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
#ifdef USE_NTLM
| CURL_VERSION_NTLM
#endif
#ifdef USE_WINDOWS_SSPI
@@ -221,7 +155,7 @@ static curl_version_info_data version_info = {
#endif
,
NULL, /* ssl_version */
0, /* ssl_version_num */
0, /* ssl_version_num, this is kept at zero */
NULL, /* zlib_version */
protocols,
NULL, /* c-ares version */
@@ -231,14 +165,10 @@ static curl_version_info_data version_info = {
curl_version_info_data *curl_version_info(CURLversion stamp)
{
#ifdef USE_SSLEAY
#ifdef USE_SSL
static char ssl_buffer[80];
long num;
getssl_version(ssl_buffer, sizeof(ssl_buffer), &num);
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
version_info.ssl_version_num = num;
/* SSL stuff is left zero if undefined */
#endif
#ifdef HAVE_LIBZ

View File

@@ -43,6 +43,7 @@ $! 8-FEB-2005, MSK, merged the two config-vms.h* files into one that uses
$! USE_SSLEAY to define if the target has SSL support built
$! in. Changed the cc/define parameter accordingly.
$! 11-FEB-2005, MSK, If [--.LIB]AMIGAOS.C and NWLIB.C are there, rename them
$! 23-MAR-2005, MSK, relocated cc_qual define so that DEBUG option would work
$!
$ on control_y then goto Common_Exit
$ ctrl_y = 1556
@@ -71,18 +72,11 @@ $ @'defines'
$ endif
$ endif
$ set def 'thisdir'
$ cc_qual = "/define=HAVE_CONFIG_H=1/OBJ=OBJDIR:"
$ link_qual = ""
$ if p1 .eqs. "LISTING" then cc_qual = cc_qual + "/LIST/MACHINE"
$ if p1 .eqs. "DEBUG"
$ then
$ cc_qual = cc_qual + "/LIST/MACHINE/DEBUG/NOOPT"
$ link_qual = "/DEBUG"
$ endif
$ msg_qual = "/OBJ=OBJDIR:"
$!
$ hpssl = 0
$ openssl = 0
$ cc_qual = "/define=HAVE_CONFIG_H=1/OBJ=OBJDIR:"
$ link_qual = ""
$ if f$trnlnm( "CURL_BUILD_NOSSL") .eqs. ""
$ then
$ if f$trnlnm( "OPENSSL") .nes. ""
@@ -95,6 +89,13 @@ $ then hpssl = 1
$ endif
$ endif
$ endif
$ if p1 .eqs. "LISTING" then cc_qual = cc_qual + "/LIST/MACHINE"
$ if p1 .eqs. "DEBUG"
$ then
$ cc_qual = cc_qual + "/LIST/MACHINE/DEBUG/NOOPT"
$ link_qual = "/DEBUG"
$ endif
$ msg_qual = "/OBJ=OBJDIR:"
$!
$! Put the right main config file in the two source directories for the build.
$!
@@ -166,8 +167,8 @@ $! the directory passed in via P1 and put it in the object library named
$! via P3
$!
$build: subroutine
$ on control_y then return ctrl_y ! SS$_CONTROLY
$ set noon
$ on control_y then goto EndLoop ! SS$_CONTROLY
$! set noon
$ set default 'p1'
$ search = p2
$ reset = f$search("reset")
@@ -200,7 +201,6 @@ $ endif
$ goto Loop
$EndLoop:
$ !purge
$ on control_y then return ctrl_y ! SS$_CONTROLY
$ set def 'origdir'
$ endsubroutine ! Build
$!
@@ -209,7 +209,7 @@ $! Only C and MSG supported.
$!
$compile: subroutine
$ on control_y then return ctrl_y ! SS$_CONTROLY
$ set noon
$! set noon
$ file = p1
$ qual = p2+p3+p4+p5+p6+p7+p8
$ typ = f$parse(file,,,"TYPE") - "."
@@ -218,7 +218,6 @@ $ cmd_msg = "MESSAGE "+msg_qual
$ x = cmd_'typ'
$ 'vo_c' x," ",file
$ 'x' 'file'
$ on control_y then return ctrl_y ! SS$_CONTROLY
$ ENDSUBROUTINE ! Compile
$!
$! Do a diff of the file specified in P1 with that in P2. If different

View File

@@ -4,13 +4,16 @@
! file and putting all the CURLE_* enum stuff into this file,
! CURLMSG.MSG. An .SDL file is created from this file with
! MESSAGE/SDL. The .H file is created using the freeware SDL tool
! against the .SDL file.
! against the .SDL file with SDL/ALPHA/LANG=CC command.
!
! With the exception of CURLE_OK, all of the messages are at
! the error severity level. With the exception of
! FTP_USER_PWD_INCORRECT, which is a shortened form of
! FTP_USER_PASSWORD_INCORRECT, these are the same names as the
! CURLE_ ones in include/curl.h
! CURLE_ ones in include/curl.h. The Message Utility manual states
! "The combined length of the prefix and the message symbol name cannot
! exceed 31 characters." With a prefix of five that leaves us with 26
! for the message name.
!
! If you update this file also update curlmsg_vms.h so that they are in sync
!

View File

@@ -13,6 +13,16 @@ command has been run ended up correctly.
specified, that will be checked/used if specified. This document includes all
the subsections currently supported.
Main sections are 'info', 'reply', 'client' and 'verify'.
<info>
<keywords>
A newline-separated list of keywords describing what this test case uses and
tests. Try to use an already used keyword. These keywords will be used for
statistical/informational purposes.
</keywords>
</info>
<reply>
<data [nocheck=1] [sendzero=yes] [base64=yes]>
<EFBFBD>data to sent to the client on its request and later verified that it arrived
@@ -57,18 +67,22 @@ number to return on a ftp SIZE command (set to -1 to make this command fail)
what to send back if the client sends a (FTP) MDTM command, set to -1 to
have it return that the file doesn't exist
</mdtm>
<servercmd>
special purpose server-command to control its behavior *before* the
reply is sent:
auth_required - server fails if no auth is provided
</servercmd>
<postcmd>
special purpose server-command to control its behavior *after* the
reply is sent
</postcmd>
<servercmd>
equivalent to <cmd> but for HTTP, one specified command is supported:
Special-commands for the server.
For FTP, these are supported:
REPLY
COUNT
DELAY
RETRWEIRDO
RETRNOSIZE
NOSAVE
SLOWDOWN
For HTTP, one specified command is supported:
"auth_required" - if this is set and a POST/PUT is made without auth, the
server will NOT wait for the full request body to get sent
</servercmd>

View File

@@ -33,7 +33,8 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test241 test242 test519 test214 test215 test216 test217 test218 \
test199 test225 test226 test227 test230 test231 test232 test228 \
test229 test233 test234 test235 test236 test520 test237 test238 \
test239 test243 test245 test246
test239 test243 test245 test246 test247 test248 test249 test250 \
test251
# The following tests have been removed from the dist since they no longer
# work. We need to fix the test suite's FTPS server first, then bring them

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
</keywords>
</info>
#
# Server-side
<reply name="1">

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
HTTP
HTTP PUT
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
followlocation
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
HTTP Range
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
HTTP
HTTP custom request
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
HTTP
HTTP HEAD
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
--write-out
</keywords>
</info>
# Server-side
<reply>
<data nocheck=true>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
HTTP proxy Basic auth
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP custom request
config file
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
{} list
</keywords>
</info>
# Server-side
<reply>
<data nocheck=1>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
connect to non-listen
FAILURE
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
HTTP Basic auth
</keywords>
</info>
#
# Server-side
<reply>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
non-existing host name
FAILURE
</keywords>
</info>
# Server-side
<reply>
<data>
@@ -7,7 +13,7 @@
# Client-side
<client>
<server>
http
none
</server>
<name>
attempt connect to non-existing host name

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
FAILURE
multiple HTTP requests
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP PUT
long URL
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
unsupported protocol
FAILURE
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
HTTP
HTTP GET
</keywords>
</info>
# Server-side
<reply>
<data nocheck=1>

39
tests/data/test247 Normal file
View File

@@ -0,0 +1,39 @@
<reply>
<mdtm>
213 20030409102659
</mdtm>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP upload time condition evaluates TRUE => skip upload
</name>
<file name="log/test247.txt">
data
to
see
that FTP
works
so does it?
</file>
<command>
ftp://%HOSTIP:%FTPPORT/247 -T log/test247.txt -z "apr 1 2005 08:00:00"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<upload>
</upload>
<protocol>
USER anonymous
PASS curl_by_daniel@haxx.se
PWD
MDTM 247
QUIT
</protocol>
</verify>

48
tests/data/test248 Normal file
View File

@@ -0,0 +1,48 @@
<reply>
<mdtm>
213 20050409102659
</mdtm>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP upload time condition evaluates FALSE => upload anyway
</name>
<file name="log/test248.txt">
data
to
see
that FTP
works
so does it?
</file>
<command>
ftp://%HOSTIP:%FTPPORT/248 -T log/test248.txt -z "apr 1 2005 08:00:00"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<upload>
data
to
see
that FTP
works
so does it?
</upload>
<protocol>
USER anonymous
PASS curl_by_daniel@haxx.se
PWD
MDTM 248
EPSV
TYPE I
STOR 248
QUIT
</protocol>
</verify>

46
tests/data/test249 Normal file
View File

@@ -0,0 +1,46 @@
#
# Server-side
<reply>
<data>
HTTP/1.1 304 Not Modified swsclose
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 1910 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 677777
Connection: close
Content-Type: text/html
</data>
</reply>
#
# Client-side
<client>
<server>
http
</server>
<name>
HTTP 304 response with "illegal" Content-Length: header
</name>
<command>
http://%HOSTIP:%HTTPPORT/249 -z "dec 12 12:00:00 1999 GMT"
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /249 HTTP/1.1
Host: 127.0.0.1:%HTTPPORT
Pragma: no-cache
Accept: */*
If-Modified-Since: Sun, 12 Dec 1999 12:00:00 GMT
</protocol>
</verify>

View File

@@ -1,3 +1,11 @@
<info>
<keywords>
HTTP
HTTP GET
followlocation
--max-redirs
</keywords>
</info>
# Server-side
<reply>
<data>

51
tests/data/test250 Normal file
View File

@@ -0,0 +1,51 @@
#
# Server-side
<reply>
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
<servercmd>
SLOWDOWN
</servercmd>
</reply>
#
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP dir list PASV with slow response
</name>
<command>
ftp://%HOSTIP:%FTPPORT/
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
filter off really nothing
</strip>
<protocol>
USER anonymous
PASS curl_by_daniel@haxx.se
PWD
EPSV
TYPE A
LIST
QUIT
</protocol>
</verify>

51
tests/data/test251 Normal file
View File

@@ -0,0 +1,51 @@
# Server-side
<reply>
<data>
total 20
drwxr-xr-x 8 98 98 512 Oct 22 13:06 .
drwxr-xr-x 8 98 98 512 Oct 22 13:06 ..
drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT
-r--r--r-- 1 0 1 35 Jul 16 1996 README
lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin
dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev
drwxrwxrwx 2 98 98 512 May 29 16:04 download.html
dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc
drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub
dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr
</data>
<servercmd>
SLOWDOWN
</servercmd>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP dir list, PORT with specified IP and slow response
</name>
<command>
ftp://%HOSTIP:%FTPPORT/ -P %HOSTIP
</command>
</client>
# Verify data after the test has been "shot"
<verify>
# strip all kinds of PORT, EPRT and LPRT curl can do
<strip>
^PORT 127,0,0,1,.*
^EPRT.*
^LPRT.*
</strip>
<protocol>
USER anonymous
PASS curl_by_daniel@haxx.se
PWD
PORT 127,0,0,1,243,212
TYPE A
LIST
QUIT
</protocol>
</verify>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
HTTP
HTTP GET
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,10 @@
<info>
<keywords>
HTTP
HTTP GET
cookies
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,9 @@
<info>
<keywords>
HTTP
HTTP GET
</keywords>
</info>
# Server-side
<reply>
<data>

View File

@@ -1,3 +1,11 @@
<info>
<keywords>
HTTP
HTTP GET
timeout
FAILURE
</keywords>
</info>
# Server-side
<reply>
<data>

Some files were not shown because too many files have changed in this diff Show More