Compare commits
105 Commits
curl-7_19_
...
curl-7_19_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
042cc1f69e | ||
![]() |
90b804d3fa | ||
![]() |
4bc603a0cc | ||
![]() |
6c3f74b946 | ||
![]() |
8d78a33e60 | ||
![]() |
df07537ccf | ||
![]() |
de25ed3f37 | ||
![]() |
40edf25866 | ||
![]() |
7b7db23633 | ||
![]() |
794b4da840 | ||
![]() |
e9ea3ba4a2 | ||
![]() |
d207ea1652 | ||
![]() |
625d06ac79 | ||
![]() |
3460225590 | ||
![]() |
ea6531cf32 | ||
![]() |
2afb88e2ce | ||
![]() |
6c9f37d263 | ||
![]() |
735955282b | ||
![]() |
dd056e54e2 | ||
![]() |
f5548973ab | ||
![]() |
07dc741e18 | ||
![]() |
8b66981ce0 | ||
![]() |
3a7e8c9f5f | ||
![]() |
fb90b43432 | ||
![]() |
0302c21253 | ||
![]() |
9182a46233 | ||
![]() |
51b46f451f | ||
![]() |
11f3690201 | ||
![]() |
5784a37f91 | ||
![]() |
af91ff0e06 | ||
![]() |
be3a78f583 | ||
![]() |
7f22da5230 | ||
![]() |
5af0629ba5 | ||
![]() |
a776e5ad31 | ||
![]() |
6e422c447a | ||
![]() |
4608d0157e | ||
![]() |
a24fe59ee4 | ||
![]() |
4ad296c60b | ||
![]() |
0517fa153c | ||
![]() |
8f81fd6be5 | ||
![]() |
1472be4d3e | ||
![]() |
8925527fef | ||
![]() |
8cdc220bc0 | ||
![]() |
d315d41a12 | ||
![]() |
4f7687895d | ||
![]() |
07d46886df | ||
![]() |
b79c8f527f | ||
![]() |
0cf10ae4d7 | ||
![]() |
debe0b561d | ||
![]() |
9ddc7ad038 | ||
![]() |
9a4c887c4a | ||
![]() |
de41c6ef43 | ||
![]() |
002cf105c6 | ||
![]() |
fb8fdf9273 | ||
![]() |
517b8ed057 | ||
![]() |
d3d7ed1766 | ||
![]() |
77fd094090 | ||
![]() |
c65f9acdc7 | ||
![]() |
5c4cdcb2d5 | ||
![]() |
b1233c7e4d | ||
![]() |
4ebe4b907b | ||
![]() |
bf44d0f640 | ||
![]() |
73cf99c052 | ||
![]() |
44c02227e9 | ||
![]() |
77da9a0087 | ||
![]() |
42d2353e74 | ||
![]() |
4b441ebac5 | ||
![]() |
01140217f5 | ||
![]() |
71f3877f3a | ||
![]() |
83d135f990 | ||
![]() |
d4ac3d53fc | ||
![]() |
f0332c0b58 | ||
![]() |
bdd4294e79 | ||
![]() |
dcf92bffd2 | ||
![]() |
a2256e899b | ||
![]() |
8b6805572a | ||
![]() |
607253c2d0 | ||
![]() |
09f4a1c5e5 | ||
![]() |
5c9fff9c6e | ||
![]() |
99b4912688 | ||
![]() |
0a6312d66f | ||
![]() |
a97f52db20 | ||
![]() |
5267be57f7 | ||
![]() |
e813bf31d7 | ||
![]() |
1bd0be0361 | ||
![]() |
996c8ca7c2 | ||
![]() |
fec65fbff6 | ||
![]() |
de4610a55f | ||
![]() |
6e34c2d59a | ||
![]() |
34b09398d5 | ||
![]() |
0516ce7786 | ||
![]() |
bb86462ed7 | ||
![]() |
8fa8df95fb | ||
![]() |
82ca52713b | ||
![]() |
f29e383575 | ||
![]() |
5aeef9c1c8 | ||
![]() |
ddd3fe5948 | ||
![]() |
5591550167 | ||
![]() |
6bb9ef8de4 | ||
![]() |
14a6788535 | ||
![]() |
6f86826516 | ||
![]() |
0e6ed13454 | ||
![]() |
b914f45e9e | ||
![]() |
3ed66094e8 | ||
![]() |
718004d9b5 |
222
CHANGES
222
CHANGES
@@ -6,6 +6,228 @@
|
||||
|
||||
Changelog
|
||||
|
||||
Version 7.19.4 (3 March 2009)
|
||||
|
||||
Daniel Stenberg (3 Mar 2009)
|
||||
- David Kierznowski notified us about a security flaw
|
||||
(http://curl.haxx.se/docs/adv_20090303.html also known as CVE-2009-0037) in
|
||||
which previous libcurl versions (by design) can be tricked to access an
|
||||
arbitrary local/different file instead of a remote one when
|
||||
CURLOPT_FOLLOWLOCATION is enabled. This flaw is now fixed in this release
|
||||
together this the addition of two new setopt options for controlling this
|
||||
new behavior:
|
||||
|
||||
o CURLOPT_REDIR_PROTOCOLS controls what protocols libcurl is allowed to
|
||||
follow to when CURLOPT_FOLLOWLOCATION is enabled. By default, this option
|
||||
excludes the FILE and SCP protocols and thus you nee to explicitly allow
|
||||
them in your app if you really want that behavior.
|
||||
|
||||
o CURLOPT_PROTOCOLS controls what protocol(s) libcurl is allowed to fetch
|
||||
using the primary URL option. This is useful if you want to allow a user or
|
||||
other outsiders control what URL to pass to libcurl and yet not allow all
|
||||
protocols libcurl may have been built to support.
|
||||
|
||||
Daniel Stenberg (27 Feb 2009)
|
||||
- Senthil Raja Velu reported a problem when CURLOPT_INTERFACE and
|
||||
CURLOPT_LOCALPORT were used together (the local port bind failed), and
|
||||
Markus Koetter provided the fix!
|
||||
|
||||
Daniel Stenberg (25 Feb 2009)
|
||||
- As Daniel Fandrich figured out, we must do the GnuTLS initing in the
|
||||
curl_global_init() function to properly maintain the performing functions
|
||||
thread-safe. We've previously (28 April 2007) moved the init to a later time
|
||||
just to avoid it to fail very early when libgcrypt dislikes the situation,
|
||||
but that move was bad and the fix should rather be in libgcrypt or
|
||||
elsewhere.
|
||||
|
||||
Daniel Stenberg (24 Feb 2009)
|
||||
- Brian J. Murrell found out that Negotiate proxy authentication didn't work.
|
||||
It happened because the code used the struct for server-based auth all the
|
||||
time for both proxy and server auth which of course was wrong.
|
||||
|
||||
Daniel Stenberg (23 Feb 2009)
|
||||
- After a bug reported by James Cheng I've made curl_easy_getinfo() for
|
||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD return
|
||||
-1 if the sizes aren't know. Previously these returned 0, make it impossible
|
||||
to detect the difference between actually zero and unknown.
|
||||
|
||||
Yang Tse (23 Feb 2009)
|
||||
- Daniel Johnson provided a shell script that will perform all the steps needed
|
||||
to build a Mac OS X fat ppc/i386 or ppc64/x86_64 libcurl.framework
|
||||
|
||||
Daniel Stenberg (23 Feb 2009)
|
||||
- I renamed everything in the windows builds files that used the name 'curllib'
|
||||
to the proper 'libcurl' as clearly this caused confusion.
|
||||
|
||||
Yang Tse (20 Feb 2009)
|
||||
- Do not halt compilation when using VS2008 to build a Windows 2000 target.
|
||||
|
||||
Daniel Stenberg (20 Feb 2009)
|
||||
- Linus Nielsen Feltzing reported and helped me repeat and fix a problem with
|
||||
FTP with the multi interface: when a transfer fails, like when aborted by a
|
||||
write callback, the control connection was wrongly closed and thus not
|
||||
re-used properly.
|
||||
|
||||
This change is also an attempt to cleanup the code somewhat in this area, as
|
||||
now the FTP code attempts to keep (better) track on pending responses
|
||||
necessary to get read in ftp_done().
|
||||
|
||||
Daniel Stenberg (19 Feb 2009)
|
||||
- Patrik Thunstrom reported a problem and helped me repeat it. It turned out
|
||||
libcurl did a superfluous 1000ms wait when doing SFTP downloads!
|
||||
|
||||
We read data with libssh2 while doing the "DO" operation for SFTP and then
|
||||
when we were about to start getting data for the actual file part, the
|
||||
"TRANSFER" part, we waited for socket action (in 1000ms) before doing a
|
||||
libssh2-read. But in this case libssh2 had already read and buffered the
|
||||
data so we ended up always just waiting 1000ms before we get working on the
|
||||
data!
|
||||
|
||||
Patrick Monnerat (18 Feb 2009)
|
||||
- FTP downloads (i.e.: RETR) ending with code 550 now return error
|
||||
CURLE_REMOTE_FILE_NOT_FOUND instead of CURLE_FTP_COULDNT_RETR_FILE.
|
||||
|
||||
Daniel Stenberg (17 Feb 2009)
|
||||
- Kamil Dudka made NSS-powered builds compile and run again!
|
||||
|
||||
- A second follow-up change by Andre Guibert de Bruet to fix a related memory
|
||||
leak like that fixed on the 14th. When zlib returns failure, we need to
|
||||
cleanup properly before returning error.
|
||||
|
||||
- CURLOPT_FTP_CREATE_MISSING_DIRS can now be set to 2 in addition to 1 for
|
||||
plain FTP connections, and it will then allow MKD to fail once and retry the
|
||||
CWD afterwards. This is especially useful if you're doing many simultanoes
|
||||
connections against the same server and they all have this option enabled,
|
||||
as then CWD may first fail but then another connection does MKD before this
|
||||
connection and thus MKD fails but trying CWD works! The numbers can
|
||||
(should?) now be set with the convenience enums now called
|
||||
CURLFTP_CREATE_DIR and CURLFTP_CREATE_DIR_RETRY.
|
||||
|
||||
Tests has proven that if you're making an application that uploads a set of
|
||||
files to an ftp server, you will get a noticable gain in speed if you're
|
||||
using multiple connections and this option will be then be very useful.
|
||||
|
||||
Daniel Stenberg (14 Feb 2009)
|
||||
- Andre Guibert de Bruet found and fixed a memory leak in the content encoding
|
||||
code, which could happen on libz errors.
|
||||
|
||||
Daniel Fandrich (12 Feb 2009)
|
||||
- Added support for Digest and NTLM authentication using GnuTLS.
|
||||
|
||||
Daniel Stenberg (11 Feb 2009)
|
||||
- CURLINFO_CONDITION_UNMET was added to allow an application to get to know if
|
||||
the condition in the previous request was unmet. This is typically a time
|
||||
condition set with CURLOPT_TIMECONDITION and was previously not possible to
|
||||
reliably figure out. From bug report #2565128
|
||||
(http://curl.haxx.se/bug/view.cgi?id=2565128) filed by Jocelyn Jaubert.
|
||||
|
||||
Daniel Fandrich (4 Feb 2009)
|
||||
- Don't add the standard /usr/lib or /usr/include paths to LDFLAGS and CPPFLAGS
|
||||
(respectively) when --with-ssl=/usr is used (patch based on FreeBSD).
|
||||
|
||||
- Added an explicit buffer limit check in msdosify() (patch based on FreeBSD).
|
||||
This couldn't ever overflow in curl, but might if the code were used
|
||||
elsewhere or under different conditions.
|
||||
|
||||
Daniel Stenberg (3 Feb 2009)
|
||||
- Hidemoto Nakada provided a small fix that makes it possible to get the
|
||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD size from file:// "transfers" with
|
||||
CURLOPT_NOBODY set true.
|
||||
|
||||
Daniel Stenberg (2 Feb 2009)
|
||||
- Patrick Scott found a rather large memory leak when using the multi
|
||||
interface and setting CURLMOPT_MAXCONNECTS to something less than the number
|
||||
of handles you add to the multi handle. All the connections that didn't fit
|
||||
in the cache would not be properly disconnected nor freed!
|
||||
|
||||
- Craig A West brought us: libcurl now defaults to do CONNECT with HTTP
|
||||
version 1.1 instead of 1.0 like before. This change also introduces the new
|
||||
proxy type for libcurl called 'CURLPROXY_HTTP_1_0' that then allows apps to
|
||||
switch (back) to CONNECT 1.0 requests. The curl tool also got a --proxy1.0
|
||||
option that works exactly like --proxy but sets CURLPROXY_HTTP_1_0.
|
||||
|
||||
I updated all test cases cases that use CONNECT and I tried to do some using
|
||||
--proxy1.0 and some updated to do CONNECT 1.1 to get both versions run.
|
||||
|
||||
Daniel Stenberg (31 Jan 2009)
|
||||
- When building with c-ares 1.6.1 (not yet released) or later and IPv6 support
|
||||
enabled, we can now take advantage of its brand new AF_UNSPEC support in
|
||||
ares_gethostbyname(). This makes test case 241 finally run fine for me with
|
||||
this setup since it now parses the "::1 ip6-localhost" line fine in my
|
||||
/etc/hosts file!
|
||||
|
||||
Daniel Stenberg (30 Jan 2009)
|
||||
- Scott Cantor filed bug report #2550061
|
||||
(http://curl.haxx.se/bug/view.cgi?id=2550061) mentioning that I failed to
|
||||
properly make sure that the VC9 makefiles got included in the latest
|
||||
release. I've now fixed the release script and verified it so next release
|
||||
will hopefully include them properly!
|
||||
|
||||
Daniel Fandrich (30 Jan 2009)
|
||||
- Fixed --disable-proxy for FTP and SOCKS. Thanks to Daniel Egger for
|
||||
reporting.
|
||||
|
||||
Yang Tse (29 Jan 2009)
|
||||
- Introduced curl_sspi.c and curl_sspi.h for the implementation of functions
|
||||
Curl_sspi_global_init() and Curl_sspi_global_cleanup() which previously were
|
||||
named Curl_ntlm_global_init() and Curl_ntlm_global_cleanup() in http_ntlm.c
|
||||
Also adjusted socks_sspi.c to remove the link-time dependency on the Windows
|
||||
SSPI library using it now in the same way as it was done in http_ntlm.c.
|
||||
|
||||
Daniel Stenberg (28 Jan 2009)
|
||||
- Markus Moeller introduced two new options to libcurl:
|
||||
CURLOPT_SOCKS5_GSSAPI_SERVICE and CURLOPT_SOCKS5_GSSAPI_NEC to allow libcurl
|
||||
to do GSS-style authentication with SOCKS5 proxies. The curl tool got the
|
||||
options called --socks5-gssapi-service and --socks5-gssapi-nec to enable
|
||||
these.
|
||||
|
||||
Daniel Stenberg (26 Jan 2009)
|
||||
- Chad Monroe provided the new CURLOPT_TFTP_BLKSIZE option that allows an app
|
||||
to set desired block size to use for TFTP transfers instead of the default
|
||||
512 bytes.
|
||||
|
||||
- The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
|
||||
disable "rfc4507bis session ticket support". rfc4507bis was later turned
|
||||
into the proper RFC5077 it seems: http://tools.ietf.org/html/rfc5077
|
||||
|
||||
The enabled extension concerns the session management. I wonder how often
|
||||
libcurl stops a connection and then resumes a TLS session. also, sending the
|
||||
session data is some overhead. .I suggest that you just use your proposed
|
||||
patch (which explicitly disables TICKET).
|
||||
|
||||
If someone writes an application with libcurl and openssl who wants to
|
||||
enable the feature, one can do this in the SSL callback.
|
||||
|
||||
Sharad Gupta brought this to my attention. Peter Sylvester helped me decide
|
||||
on the proper action.
|
||||
|
||||
- Alexey Borzov filed bug report #2535504
|
||||
(http://curl.haxx.se/bug/view.cgi?id=2535504) pointing out that realms with
|
||||
quoted quotation marks in HTTP Digest headers didn't work. I've now added
|
||||
test case 1095 that verifies my fix.
|
||||
|
||||
- Craig A West brought CURLOPT_NOPROXY and the corresponding --noproxy option.
|
||||
They basically offer the same thing the NO_PROXY environment variable only
|
||||
offered previously: list a set of host names that shall not use the proxy
|
||||
even if one is specified.
|
||||
|
||||
Daniel Fandrich (20 Jan 2009)
|
||||
- Call setlocale() for libtest tests to test the effects of locale-induced
|
||||
libc changes on libcurl.
|
||||
|
||||
- Fixed a couple more locale-dependent toupper conversions, mainly for
|
||||
clarity. This does fix one problem that causes ;type=i FTP URLs
|
||||
to fail in the Turkish locale when CURLOPT_PROXY_TRANSFER_MODE is
|
||||
used (test case 561)
|
||||
|
||||
- Added tests 561 and 1091 through 1094 to test various combinations
|
||||
of ;type= and ;mode= URLs that could potentially fail in the Turkish
|
||||
locale.
|
||||
|
||||
Daniel Stenberg (20 Jan 2009)
|
||||
- Lisa Xu pointed out that the ssh.obj file was missing from the
|
||||
lib/Makefile.vc6 file (and thus from the vc8 and vc9 ones too).
|
||||
|
||||
Version 7.19.3 (19 January 2009)
|
||||
|
||||
Daniel Stenberg (16 Jan 2009)
|
||||
|
49
MacOSX-Framework
Executable file
49
MacOSX-Framework
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# This script performs all of the steps needed to build a 32 bit
|
||||
# universal binary libcurl.framework for Mac OS X 10.4 or greater.
|
||||
|
||||
VERSION=`/usr/bin/sed -ne 's/^#define LIBCURL_VERSION "\(.*\)"/\1/p' include/curl/curlver.h`
|
||||
|
||||
SDK='/Developer/SDKs/MacOSX10.4u.sdk'
|
||||
|
||||
MINVER='-mmacosx-version-min=10.4'
|
||||
|
||||
ARCHES='-arch ppc -arch i386'
|
||||
|
||||
# Use these values instead to produce a 64 bit framework that only works on 10.5.
|
||||
# You can't currently build a combined 32/64 framework.
|
||||
#SDK='/Developer/SDKs/MacOSX10.5.sdk'
|
||||
#
|
||||
#MINVER='-mmacosx-version-min=10.5'
|
||||
#
|
||||
#ARCHES='-arch ppc64 -arch x86_64'
|
||||
|
||||
|
||||
if test -d $SDK; then
|
||||
echo "Configuring libcurl for 32 bit universal framework..."
|
||||
./configure --disable-dependency-tracking --disable-static --with-gssapi \
|
||||
CFLAGS="-isysroot $SDK $ARCHES $MINVER" \
|
||||
LDFLAGS="-Wl,-syslibroot,$SDK $ARCHES $MINVER -Wl,-headerpad_max_install_names"
|
||||
|
||||
echo "Building libcurl..."
|
||||
make
|
||||
|
||||
echo "Creating framework..."
|
||||
rm -r libcurl.framework
|
||||
mkdir -p libcurl.framework/Versions/A/Resources
|
||||
cp lib/.libs/libcurl.dylib libcurl.framework/Versions/A/libcurl
|
||||
install_name_tool -id @executable_path/../Frameworks/libcurl.framework/Versions/A/libcurl libcurl.framework/Versions/A/libcurl
|
||||
/usr/bin/sed -e "s/7\.12\.3/$VERSION/" lib/libcurl.plist >libcurl.framework/Versions/A/Resources/Info.plist
|
||||
mkdir -p libcurl.framework/Versions/A/Headers
|
||||
cp include/curl/*.h libcurl.framework/Versions/A/Headers
|
||||
cd libcurl.framework
|
||||
ln -fs Versions/A/libcurl libcurl
|
||||
ln -fs Versions/A/Resources Resources
|
||||
ln -fs Versions/A/Headers Headers
|
||||
cd Versions
|
||||
ln -fs A Current
|
||||
|
||||
echo "libcurl.framework is built and can now be included in other projects."
|
||||
else
|
||||
echo "Building libcurl.framework requires Mac OS X 10.4 or later with the MacOSX10.4u SDK installed."
|
||||
fi
|
@@ -27,7 +27,7 @@ ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \
|
||||
curl-style.el sample.emacs RELEASE-NOTES buildconf buildconf.bat \
|
||||
libcurl.pc.in vc6curl.dsw
|
||||
libcurl.pc.in vc6curl.dsw MacOSX-Framework
|
||||
|
||||
bin_SCRIPTS = curl-config
|
||||
|
||||
|
101
RELEASE-NOTES
101
RELEASE-NOTES
@@ -1,54 +1,57 @@
|
||||
Curl and libcurl 7.19.3
|
||||
Curl and libcurl 7.19.4
|
||||
|
||||
Public curl releases: 109
|
||||
Command line options: 128
|
||||
curl_easy_setopt() options: 158
|
||||
Public curl releases: 110
|
||||
Command line options: 132
|
||||
curl_easy_setopt() options: 163
|
||||
Public functions in libcurl: 58
|
||||
Known libcurl bindings: 37
|
||||
Contributors: 683
|
||||
Known libcurl bindings: 38
|
||||
Contributors: 700
|
||||
|
||||
This release includes the following security-related fix:
|
||||
|
||||
o CVE-2009-0037 with the curl advisory here:
|
||||
http://curl.haxx.se/docs/adv_20090303.html
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o CURLAUTH_DIGEST_IE bit added for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH
|
||||
o VC9 Makefiles were added to the release package
|
||||
o Added CURLOPT_NOPROXY and the corresponding --noproxy
|
||||
o the OpenSSL-specific code disables TICKET (rfc5077) which is enabled by
|
||||
default in openssl 0.9.8j
|
||||
o Added CURLOPT_TFTP_BLKSIZE
|
||||
o Added CURLOPT_SOCKS5_GSSAPI_SERVICE and CURLOPT_SOCKS5_GSSAPI_NEC - with
|
||||
the corresponding curl options --socks5-gssapi-service and
|
||||
--socks5-gssapi-nec
|
||||
o Improved IPv6 support when built with with c-ares >= 1.6.1
|
||||
o Added CURLPROXY_HTTP_1_0 and --proxy1.0
|
||||
o Added docs/libcurl/symbols-in-versions
|
||||
o Added CURLINFO_CONDITION_UNMET
|
||||
o Added support for Digest and NTLM authentication using GnuTLS
|
||||
o CURLOPT_FTP_CREATE_MISSING_DIRS can now be set to 2 to retry the CWD even
|
||||
when MKD fails
|
||||
o GnuTLS initing moved to curl_global_init()
|
||||
o Added CURLOPT_REDIR_PROTOCOLS and CURLOPT_PROTOCOLS
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o build failure when disabling FTP but enabling GSS
|
||||
o fixed several calls to memory functions that didn't check return codes
|
||||
o memory leak for SSL connects with libcurl/NSS when CURLOPT_ISSUERCERT was
|
||||
used
|
||||
o re-use of connections with the multi interface when multiple handles used
|
||||
the same server
|
||||
o memory leak with HTTP GSS/kerberos authentication
|
||||
o removed the default use of "Pragma: no-cache"
|
||||
o fix SCP/SFTP busyloop by using a new libssh2 1.0 function
|
||||
o bad fclose() after a fatal error in cookie code
|
||||
o curl_multi_remove_handle() when the handle was in use in a HTTP pipeline
|
||||
o GSS authentication infinite loop problem
|
||||
o 550 response from SIZE no longer treated as missing file
|
||||
o ftps:// control connections now use explicit protection level
|
||||
o dotted IPv6 addresses longer than 39 bytes failed
|
||||
o curl_easy_duphandle() doesn't try to duplicate the connection cache pointer
|
||||
o build failure on OS/400 when enabling IPv6
|
||||
o better detection of SFTP failures
|
||||
o improved connection re-use for subsequent SCP and SFTP transfers
|
||||
o multi interface does less busy-loops for SCP and SFTP transfers with libssh2
|
||||
1.0 or later
|
||||
o curl_multi_timeout() no longer returns timeout 0 when there's still more
|
||||
than 0 but less than 999 microseconds left
|
||||
o the multi_socket API and HTTP pipelining now work a lot better when combined
|
||||
o SFTP seek/resume beyond 32bit file sizes
|
||||
o fixed breakage with --with-ssl --disable-verbose
|
||||
o TTL "leak" in the DNS cache
|
||||
o improved NSS initing
|
||||
o curl_easy_reset now resets more options
|
||||
o rare Location: follow bug with the multi interface
|
||||
o the configure script can now detect gnutls with pkg-config
|
||||
o curlbuild.h was adjusted for SunPro compilers
|
||||
o CURLOPT_COOKIELIST set to "SESS" on an easy handle with no cookies data
|
||||
o fixed timeouts for TFTP
|
||||
o fixed PPC builds
|
||||
o missing ssh.obj in VS makefiles
|
||||
o FTP ;type=i URLs now work with CURLOPT_PROXY_TRANSFER_MODE in Turkish
|
||||
locale
|
||||
o realms with quoted quotation marks in HTTP Digest headers
|
||||
o VC9 makefiles are now really included
|
||||
o multi interface memory leak with CURLMOPT_MAXCONNECTS set
|
||||
o CURLINFO_CONTENT_LENGTH_DOWNLOAD size from file:// "transfers" with
|
||||
CURLOPT_NOBODY set true
|
||||
o memory leak on some libz errors for content encodings
|
||||
o NSS-enabled build is repaired
|
||||
o superfluous wait in SFTP downloads removed
|
||||
o FTP with the multi interface no longer kills the control connection as
|
||||
easily on transfer failures
|
||||
o compilation halting when using VS2008 to build a Windows 2000 target
|
||||
o ease creation of libcurl Mac OS X Framework
|
||||
o CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD are -1
|
||||
if unknown
|
||||
o Negotiate proxy authentication
|
||||
o CURLOPT_INTERFACE and CURLOPT_LOCALPORT used together
|
||||
|
||||
This release includes the following known bugs:
|
||||
|
||||
@@ -57,11 +60,11 @@ This release includes the following known bugs:
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Yang Tse, Daniel Fandrich, Jim Meyering, Christian Krause, Andreas Wurf,
|
||||
Markus Koetter, Josef Wolf, Vlad Grachov, Pawel Kierski, Igor Novoseltsev,
|
||||
Fred Machado, Ken Hirsch, Keshav Krity, Patrick Monnerat, Mark Karpeles,
|
||||
Anthony Bryan, Peter Korsgaard, Phil Lisiecki, Bas Mevissen, Rob Crittenden,
|
||||
Emil Romanus, Karl Moerder, Daniel Black, Stefan Teleman, Michael Wallner,
|
||||
Grant Erickson, Tim Ansell, Andrew de los Reyes
|
||||
Lisa Xu, Daniel Fandrich, Craig A West, Alexey Borzov, Sharad Gupta,
|
||||
Peter Sylvester, Chad Monroe, Markus Moeller, Yang Tse, Scott Cantor,
|
||||
Patrick Scott, Hidemoto Nakada, Jocelyn Jaubert, Andre Guibert de Bruet,
|
||||
Kamil Dudka, Patrik Thunstrom, Linus Nielsen Feltzing, Mark Incley,
|
||||
Daniel Johnson, James Cheng, Brian J. Murrell, Senthil Raja Velu,
|
||||
Markus Koetter, David Kierznowski, Michal Marek
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
18
TODO-RELEASE
18
TODO-RELEASE
@@ -1,19 +1,11 @@
|
||||
To be addressed in 7.19.3 (planned release: January 2009)
|
||||
To be addressed in 7.19.5 (planned release: May 2009)
|
||||
=========================
|
||||
|
||||
|
||||
To be addressed in 7.19.4 (planned release: March 2009)
|
||||
=========================
|
||||
|
||||
205 - A. Craig West's CURLOPT_NOPROXY option
|
||||
|
||||
206 - A. Craig West's CURLOPT_HTTP_VERSION change for CONNECT
|
||||
|
||||
208 - Patch to allow GSSAPI authentication to a socks5 server
|
||||
|
||||
214 - progress bar prefix, second try (for the curl tool)
|
||||
216 - Markus Moeller's "proxy question" to reverse lookup SOCKS proxys and more
|
||||
|
||||
215 - Patch for Metalink Support (for the curl tool)
|
||||
|
||||
216 -
|
||||
220 - Take advantage of libssh2_version() that's been added for the upcoming
|
||||
1.1, to extract the run-time version number properly.
|
||||
|
||||
221 -
|
||||
|
12
ares/CHANGES
12
ares/CHANGES
@@ -1,5 +1,17 @@
|
||||
Changelog for the c-ares project
|
||||
|
||||
* February 20 2009 (Yang Tse)
|
||||
- Do not halt compilation when using VS2008 to build a Windows 2000 target.
|
||||
|
||||
* February 3 2009 (Phil Blundell)
|
||||
- If the server returns garbage or nothing at all in response to an AAAA query,
|
||||
go on and ask for A records anyway.
|
||||
|
||||
* January 31 2009 (Daniel Stenberg)
|
||||
- ares_gethostbyname() now accepts 'AF_UNSPEC' as a family for resolving
|
||||
either AF_INET6 or AF_INET. It works by accepting any of the looksups in the
|
||||
hosts file, and it resolves the AAAA field with a fallback to A.
|
||||
|
||||
* January 14 2009 (Daniel Stenberg)
|
||||
- ares.h no longer uses the HAVE_STRUCT_IN6_ADDR define check, but instead it
|
||||
now declares the private struct ares_in6_addr for all systems instead of
|
||||
|
@@ -2,8 +2,10 @@ This is what's new and changed in the c-ares 1.6.1 release:
|
||||
|
||||
Changed:
|
||||
|
||||
o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is instead
|
||||
declared and used
|
||||
o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is
|
||||
instead declared and used
|
||||
p ares_gethostbyname() now supports 'AF_UNSPEC' as a family for resolving
|
||||
either AF_INET6 or AF_INET
|
||||
|
||||
Fixed:
|
||||
|
||||
|
@@ -68,17 +68,21 @@ int ares__get_hostent(FILE *fp, int family, 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;
|
||||
}
|
||||
{
|
||||
/* It wasn't an AF_INET dotted address, then AF_UNSPEC and AF_INET6
|
||||
families are subject for this further check */
|
||||
if ((family != AF_INET) &&
|
||||
(ares_inet_pton(AF_INET6, line, &addr6) > 0)) {
|
||||
addrlen = sizeof(struct in6_addr);
|
||||
family = AF_INET6;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else if (family == AF_UNSPEC)
|
||||
family = AF_INET; /* now confirmed! */
|
||||
else if (family != AF_INET)
|
||||
/* unknown, keep moving */
|
||||
continue;
|
||||
|
||||
/* Get the canonical hostname. */
|
||||
|
@@ -61,7 +61,8 @@ struct host_query {
|
||||
char *name;
|
||||
ares_host_callback callback;
|
||||
void *arg;
|
||||
int family;
|
||||
int sent_family; /* this family is what was is being used */
|
||||
int want_family; /* this family is what is asked for in the API */
|
||||
const char *remaining_lookups;
|
||||
int timeouts;
|
||||
};
|
||||
@@ -71,29 +72,34 @@ static void host_callback(void *arg, int status, int timeouts,
|
||||
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, int family, ares_host_callback callback,
|
||||
void *arg);
|
||||
static int fake_hostent(const char *name, int family,
|
||||
ares_host_callback callback, void *arg);
|
||||
static int file_lookup(const char *name, int family, struct hostent **host);
|
||||
static void sort_addresses(struct hostent *host, const struct apattern *sortlist,
|
||||
int nsort);
|
||||
static void sort6_addresses(struct hostent *host, const struct apattern *sortlist,
|
||||
int nsort);
|
||||
static int get_address_index(const struct in_addr *addr, const struct apattern *sortlist,
|
||||
int nsort);
|
||||
static int get6_address_index(const struct in6_addr *addr, const struct apattern *sortlist,
|
||||
int nsort);
|
||||
static void sort_addresses(struct hostent *host,
|
||||
const struct apattern *sortlist, int nsort);
|
||||
static void sort6_addresses(struct hostent *host,
|
||||
const struct apattern *sortlist, int nsort);
|
||||
static int get_address_index(const struct in_addr *addr,
|
||||
const struct apattern *sortlist, int nsort);
|
||||
static int get6_address_index(const struct in6_addr *addr,
|
||||
const struct apattern *sortlist, int nsort);
|
||||
|
||||
void ares_gethostbyname(ares_channel channel, const char *name, int family,
|
||||
ares_host_callback callback, void *arg)
|
||||
{
|
||||
struct host_query *hquery;
|
||||
|
||||
/* Right now we only know how to look up Internet addresses. */
|
||||
if (family != AF_INET && family != AF_INET6)
|
||||
{
|
||||
callback(arg, ARES_ENOTIMP, 0, NULL);
|
||||
return;
|
||||
}
|
||||
/* Right now we only know how to look up Internet addresses - and unspec
|
||||
means try both basically. */
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
case AF_UNSPEC:
|
||||
break;
|
||||
default:
|
||||
callback(arg, ARES_ENOTIMP, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fake_hostent(name, family, callback, arg))
|
||||
return;
|
||||
@@ -107,13 +113,13 @@ 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);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return;
|
||||
}
|
||||
hquery->want_family = family;
|
||||
hquery->sent_family = -1; /* nothing is sent yet */
|
||||
if (!hquery->name) {
|
||||
free(hquery);
|
||||
callback(arg, ARES_ENOMEM, 0, NULL);
|
||||
return;
|
||||
}
|
||||
hquery->callback = callback;
|
||||
hquery->arg = arg;
|
||||
hquery->remaining_lookups = channel->lookups;
|
||||
@@ -136,17 +142,23 @@ static void next_lookup(struct host_query *hquery, int status_code)
|
||||
case 'b':
|
||||
/* DNS lookup */
|
||||
hquery->remaining_lookups = p + 1;
|
||||
if (hquery->family == AF_INET6)
|
||||
if ((hquery->want_family == AF_INET6) ||
|
||||
(hquery->want_family == AF_UNSPEC)) {
|
||||
/* if inet6 or unspec, start out with AAAA */
|
||||
hquery->sent_family = AF_INET6;
|
||||
ares_search(hquery->channel, hquery->name, C_IN, T_AAAA,
|
||||
host_callback, hquery);
|
||||
else
|
||||
}
|
||||
else {
|
||||
hquery->sent_family = AF_INET;
|
||||
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
|
||||
hquery);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'f':
|
||||
/* Host file lookup */
|
||||
status = file_lookup(hquery->name, hquery->family, &host);
|
||||
status = file_lookup(hquery->name, hquery->want_family, &host);
|
||||
|
||||
/* this status check below previously checked for !ARES_ENOTFOUND,
|
||||
but we should not assume that this single error code is the one
|
||||
@@ -173,33 +185,34 @@ static void host_callback(void *arg, int status, int timeouts,
|
||||
hquery->timeouts += timeouts;
|
||||
if (status == ARES_SUCCESS)
|
||||
{
|
||||
if (hquery->family == AF_INET)
|
||||
if (hquery->sent_family == AF_INET)
|
||||
{
|
||||
status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL);
|
||||
if (host && channel->nsort)
|
||||
sort_addresses(host, channel->sortlist, channel->nsort);
|
||||
}
|
||||
else if (hquery->family == AF_INET6)
|
||||
else if (hquery->sent_family == AF_INET6)
|
||||
{
|
||||
status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL);
|
||||
if (status == ARES_ENODATA)
|
||||
{
|
||||
/* The query returned something (e.g. CNAME) but there were no
|
||||
AAAA records. Try looking up A instead. */
|
||||
hquery->family = AF_INET;
|
||||
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
|
||||
hquery);
|
||||
return;
|
||||
}
|
||||
if (status == ARES_ENODATA || status == ARES_EBADRESP) {
|
||||
/* The query returned something but either there were no AAAA records (e.g. just CNAME)
|
||||
or the response was malformed. Try looking up A instead.
|
||||
We should possibly limit this attempt-next logic to AF_UNSPEC lookups only. */
|
||||
hquery->sent_family = AF_INET;
|
||||
ares_search(hquery->channel, hquery->name, C_IN, T_A,
|
||||
host_callback, hquery);
|
||||
return;
|
||||
}
|
||||
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)
|
||||
else if ((status == ARES_ENODATA || status == ARES_EBADRESP || status == ARES_ETIMEOUT) && hquery->sent_family == AF_INET6)
|
||||
{
|
||||
/* There was no AAAA. Now lookup an A */
|
||||
hquery->family = AF_INET;
|
||||
/* The AAAA query yielded no useful result. Now look up an A instead.
|
||||
We should possibly limit this attempt-next logic to AF_UNSPEC lookups only. */
|
||||
hquery->sent_family = AF_INET;
|
||||
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
|
||||
hquery);
|
||||
}
|
||||
|
@@ -223,17 +223,33 @@
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
||||
#endif
|
||||
|
||||
/* VS2008 does not support Windows build targets prior to WinXP, */
|
||||
/* so, if no build target has been defined we will target WinXP. */
|
||||
/* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
|
||||
2000 as a supported build target. VS2008 default installations provide an
|
||||
embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
|
||||
valid build target for VS2008. Popular belief is that binaries built using
|
||||
Windows SDK versions 6.X and Windows 2000 as a build target are functional */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define VS2008_MINIMUM_TARGET 0x0500
|
||||
#endif
|
||||
|
||||
/* When no build target is specified VS2008 default build target is Windows
|
||||
Vista, which leaves out even Winsows XP. If no build target has been given
|
||||
for VS2008 we will target the minimum Officially supported build target,
|
||||
which happens to be Windows XP. */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define VS2008_DEFAULT_TARGET 0x0501
|
||||
#endif
|
||||
|
||||
/* VS2008 default target settings and minimum build target check */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# define _WIN32_WINNT VS2008_DEFAULT_TARGET
|
||||
# endif
|
||||
# ifndef WINVER
|
||||
# define WINVER 0x0501
|
||||
# define WINVER VS2008_DEFAULT_TARGET
|
||||
# endif
|
||||
# if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501)
|
||||
# error VS2008 does not support Windows build targets prior to WinXP
|
||||
# if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
|
||||
# error VS2008 does not support Windows build targets prior to Windows 2000
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
5
ares/m4/.cvsignore
Normal file
5
ares/m4/.cvsignore
Normal file
@@ -0,0 +1,5 @@
|
||||
libtool.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
lt~obsolete.m4
|
@@ -277,6 +277,10 @@ for fname in .deps \
|
||||
libtool \
|
||||
libtool.m4 \
|
||||
ltmain.sh \
|
||||
ltoptions.m4 \
|
||||
ltsugar.m4 \
|
||||
ltversion.m4 \
|
||||
lt~obsolete.m4 \
|
||||
stamp-h1 \
|
||||
stamp-h2 \
|
||||
stamp-h3 ; do
|
||||
|
50
configure.ac
50
configure.ac
@@ -1171,8 +1171,11 @@ if test X"$OPT_SSL" != Xno; then
|
||||
PKGTEST="no"
|
||||
PREFIX_OPENSSL=$OPT_SSL
|
||||
LIB_OPENSSL="$PREFIX_OPENSSL/lib$libsuff"
|
||||
LDFLAGS="$LDFLAGS -L$LIB_OPENSSL"
|
||||
CPPFLAGS="$CPPFLAGS -I$PREFIX_OPENSSL/include/openssl -I$PREFIX_OPENSSL/include"
|
||||
if [ "$PREFIX_OPENSSL" != "/usr" ] ; then
|
||||
LDFLAGS="$LDFLAGS -L$LIB_OPENSSL"
|
||||
CPPFLAGS="$CPPFLAGS -I$PREFIX_OPENSSL/include"
|
||||
fi
|
||||
CPPFLAGS="$CPPFLAGS -I$PREFIX_OPENSSL/include/openssl"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -2030,6 +2033,7 @@ CURL_CHECK_FUNC_IOCTL
|
||||
CURL_CHECK_FUNC_IOCTLSOCKET
|
||||
CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL
|
||||
CURL_CHECK_FUNC_LOCALTIME_R
|
||||
CURL_CHECK_FUNC_POLL
|
||||
CURL_CHECK_FUNC_SETSOCKOPT
|
||||
CURL_CHECK_FUNC_SIGACTION
|
||||
CURL_CHECK_FUNC_SIGINTERRUPT
|
||||
@@ -2075,7 +2079,6 @@ AC_CHECK_FUNCS([basename \
|
||||
inet_addr \
|
||||
perror \
|
||||
pipe \
|
||||
poll \
|
||||
setlocale \
|
||||
setmode \
|
||||
setrlimit \
|
||||
@@ -2132,45 +2135,6 @@ if test "$ipv6" = "yes"; then
|
||||
CURL_CHECK_NI_WITHSCOPEID
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if we are Mac OS X (to disable poll)])
|
||||
disable_poll=no
|
||||
case $host in
|
||||
*-*-darwin*)
|
||||
disable_poll="yes";
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT($disable_poll)
|
||||
|
||||
if test "$disable_poll" = "no"; then
|
||||
|
||||
dnl poll() might be badly emulated, as in Mac OS X 10.3 (and other BSDs?) and
|
||||
dnl to find out we make an extra check here!
|
||||
if test "$ac_cv_func_poll" = "yes"; then
|
||||
AC_MSG_CHECKING([if poll works with NULL inputs])
|
||||
AC_RUN_IFELSE([
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h>
|
||||
#elif defined(HAVE_POLL_H)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* make this return 0 == timeout since there's nothing to read from */
|
||||
return poll((void *)0, 0, 10 /*ms*/);
|
||||
}
|
||||
],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_POLL_FINE, 1, [If you have a fine poll]),
|
||||
AC_MSG_RESULT(no),
|
||||
AC_MSG_RESULT(cross-compiling assumes yes)
|
||||
AC_DEFINE(HAVE_POLL_FINE, 1, [If you have a fine poll])
|
||||
) dnl end of AC_RUN_IFELSE
|
||||
fi dnl poll() was found
|
||||
fi dnl poll()-check is not disabled
|
||||
|
||||
dnl ************************************************************
|
||||
dnl enable non-blocking communications
|
||||
dnl
|
||||
@@ -2505,7 +2469,7 @@ fi
|
||||
if test "x$USE_WINDOWS_SSPI" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI"
|
||||
fi
|
||||
if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1"; then
|
||||
if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" -o "x$GNUTLS_ENABLED" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
|
||||
fi
|
||||
|
||||
|
40
diff-exclude
Normal file
40
diff-exclude
Normal file
@@ -0,0 +1,40 @@
|
||||
diff-exclude
|
||||
*~
|
||||
*.orig
|
||||
*.org
|
||||
*.rej
|
||||
configure
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.pid
|
||||
*.bak
|
||||
*.o
|
||||
*.lo
|
||||
*.Plo
|
||||
*.Po
|
||||
config.log
|
||||
config.status
|
||||
autom4te.cache
|
||||
*.patch
|
||||
CVS
|
||||
*.asc
|
||||
config.h
|
||||
*.la
|
||||
*.lai
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
.#*
|
||||
aclocal.m4
|
||||
hugehelp.c
|
||||
.deps
|
||||
.libs
|
||||
libcurl.pc
|
||||
curl-config
|
||||
stamp-h*
|
||||
curl
|
||||
curllib.dsp
|
||||
curllib.vcproj
|
||||
*.spec
|
||||
curl.list
|
@@ -32,7 +32,7 @@ C
|
||||
C++
|
||||
|
||||
Written by Jean-Philippe Barrette-LaPierre
|
||||
http://rrette.com/textpattern/index.php?s=cURLpp
|
||||
http://curlpp.org/
|
||||
|
||||
Ch
|
||||
|
||||
@@ -54,6 +54,10 @@ Dylan
|
||||
Written by Chris Double
|
||||
http://dylanlibs.sourceforge.net/
|
||||
|
||||
Eiffel
|
||||
Written by Eiffel Software
|
||||
http://curl.haxx.se/libcurl/eiffel/
|
||||
|
||||
Euphoria
|
||||
|
||||
Written by Ray Smith
|
||||
|
71
docs/FAQ
71
docs/FAQ
@@ -1,4 +1,4 @@
|
||||
Updated: Jan 14, 2009 (http://curl.haxx.se/docs/faq.html)
|
||||
Updated: Feb 23, 2009 (http://curl.haxx.se/docs/faq.html)
|
||||
_ _ ____ _
|
||||
___| | | | _ \| |
|
||||
/ __| | | | |_) | |
|
||||
@@ -26,7 +26,7 @@ FAQ
|
||||
2.1.2 only the libssl lib is missing
|
||||
2.2 Does curl work/build with other SSL libraries?
|
||||
2.3 Where can I find a copy of LIBEAY32.DLL?
|
||||
2.4 Does curl support Socks (RFC 1928) ?
|
||||
2.4 Does curl support SOCKS (RFC 1928) ?
|
||||
|
||||
3. Usage Problems
|
||||
3.1 curl: (1) SSL is disabled, https: not supported
|
||||
@@ -42,7 +42,7 @@ FAQ
|
||||
3.11 How do I POST with a different Content-Type?
|
||||
3.12 Why do FTP specific features over HTTP proxy fail?
|
||||
3.13 Why does my single/double quotes fail?
|
||||
3.14 Does curl support javascript or pac (automated proxy config)?
|
||||
3.14 Does curl support Javascript or PAC (automated proxy config)?
|
||||
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?
|
||||
@@ -71,6 +71,7 @@ FAQ
|
||||
4.14 Redirects work in browser but not with curl!
|
||||
4.15 FTPS doesn't work
|
||||
4.16 My HTTP POST or PUT requests are slow!
|
||||
4.17 Non-functional connect timeouts on Windows
|
||||
|
||||
5. libcurl Issues
|
||||
5.1 Is libcurl thread-safe?
|
||||
@@ -95,7 +96,7 @@ FAQ
|
||||
6.4 I have a program that uses LGPL libraries, can I use libcurl?
|
||||
6.5 Can I modify curl/libcurl for my program and keep the changes secret?
|
||||
6.6 Can you please change the curl/libcurl license to XXXX?
|
||||
6.7 What are my obligations when using libcurl in my commerical apps?
|
||||
6.7 What are my obligations when using libcurl in my commercial apps?
|
||||
|
||||
7. PHP/CURL Issues
|
||||
7.1 What is PHP/CURL?
|
||||
@@ -399,7 +400,7 @@ FAQ
|
||||
accurate and up-to-date pointers to recent OpenSSL DLLs and other binary
|
||||
packages.
|
||||
|
||||
2.4 Does curl support Socks (RFC 1928) ?
|
||||
2.4 Does curl support SOCKS (RFC 1928) ?
|
||||
|
||||
Yes, SOCKS 4 and 5 are supported.
|
||||
|
||||
@@ -557,27 +558,27 @@ FAQ
|
||||
Remember that curl works and runs on more operating systems than most single
|
||||
individuals have ever tried.
|
||||
|
||||
3.14 Does curl support javascript or pac (automated proxy config)?
|
||||
3.14 Does curl support Javascript or PAC (automated proxy config)?
|
||||
|
||||
Many web pages do magic stuff using embedded javascript. Curl and libcurl
|
||||
Many web pages do magic stuff using embedded Javascript. Curl and libcurl
|
||||
have no built-in support for that, so it will be treated just like any other
|
||||
contents.
|
||||
|
||||
.pac files are a netscape invention and are sometimes used by organizations
|
||||
to allow them to differentiate which proxies to use. The .pac contents is
|
||||
just a javascript program that gets invoked by the browser and that returns
|
||||
the name of the proxy to connect to. Since curl doesn't support javascript,
|
||||
just a Javascript program that gets invoked by the browser and that returns
|
||||
the name of the proxy to connect to. Since curl doesn't support Javascript,
|
||||
it can't support .pac proxy configuration either.
|
||||
|
||||
Some work-arounds usually suggested to overcome this javascript dependency:
|
||||
Some work-arounds usually suggested to overcome this Javascript dependency:
|
||||
|
||||
- Depending on the javascript complexity, write up a script that
|
||||
- Depending on the Javascript complexity, write up a script that
|
||||
translates it to another language and execute that.
|
||||
|
||||
- Read the javascript code and rewrite the same logic in another language.
|
||||
- Read the Javascript code and rewrite the same logic in another language.
|
||||
|
||||
- Implement a javascript interpreter, people have successfully used the
|
||||
Mozilla javascript engine in the past.
|
||||
- Implement a Javascript interpreter, people have successfully used the
|
||||
Mozilla Javascript engine in the past.
|
||||
|
||||
- Ask your admins to stop this, for a static proxy setup or similar.
|
||||
|
||||
@@ -658,21 +659,22 @@ FAQ
|
||||
|
||||
4.2 Why do I get problems when I use & or % in the URL?
|
||||
|
||||
In general unix shells, the & letter is treated special and when used, it
|
||||
In general unix shells, the & symbol is treated specially and when used, it
|
||||
runs the specified command in the background. To safely send the & as a part
|
||||
of a URL, you should quote the entire URL by using single (') or double (")
|
||||
quotes around it.
|
||||
quotes around it. Similar problems can also occur on some shells with other
|
||||
characters, including ?*!$~(){}<>\|;`. When in doubt, quote the URL.
|
||||
|
||||
An example that would invoke a remote CGI that uses &-letters could be:
|
||||
An example that would invoke a remote CGI that uses &-symbols could be:
|
||||
|
||||
curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl'
|
||||
|
||||
In Windows, the standard DOS shell treats the %-letter specially and you
|
||||
need to use TWO %-letters for each single one you want to use in the URL.
|
||||
In Windows, the standard DOS shell treats the %-symbol specially and you
|
||||
need to use TWO %-symbols for each single one you want to use in the URL.
|
||||
|
||||
Also note that if you want the literal %-letter to be part of the data you
|
||||
Also note that if you want the literal %-symbol to be part of the data you
|
||||
pass in a POST using -d/--data you must encode it as '%25' (which then also
|
||||
needs the %-letter doubled on Windows machines).
|
||||
needs the %-symbol doubled on Windows machines).
|
||||
|
||||
4.3 How can I use {, }, [ or ] to specify multiple URLs?
|
||||
|
||||
@@ -787,7 +789,7 @@ FAQ
|
||||
|
||||
This is supported in curl 7.10.6 or later. No earlier curl version knows
|
||||
of this magic. Later versions require the OpenSSL or Microsoft Windows
|
||||
libraries to provide this functionality. Using GnuTLS or NSS libraries will
|
||||
libraries to provide this functionality. Using the NSS library will
|
||||
not provide NTLM authentication functionality in curl.
|
||||
|
||||
NTLM is a Microsoft proprietary protocol. Proprietary formats are evil. You
|
||||
@@ -848,7 +850,7 @@ FAQ
|
||||
- Meta tags. You can write a HTML tag that will cause the browser to
|
||||
redirect to another given URL after a certain time.
|
||||
|
||||
- Javascript. You can write a javascript program embeded in a HTML page
|
||||
- Javascript. You can write a Javascript program embedded in a HTML page
|
||||
that redirects the browser to another given URL.
|
||||
|
||||
There is no way to make curl follow these redirects. You must either
|
||||
@@ -884,6 +886,23 @@ FAQ
|
||||
You can disable libcurl's use of the Expect: header the same way you disable
|
||||
any header, using -H / CURLOPT_HTTPHEADER, or by forcing it to use HTTP 1.0.
|
||||
|
||||
4.17 Non-functional connect timeouts
|
||||
|
||||
In most Windows setups having a timeout longer than 21 seconds make no
|
||||
difference, as it will only send 3 TCP SYN packets and no more. The second
|
||||
packet sent three seconds after the first and the third six seconds after
|
||||
the second. No more than three packets are sent, no matter how long the
|
||||
timeout is set.
|
||||
|
||||
See option TcpMaxConnectRetransmissions on this page:
|
||||
http://support.microsoft.com/?scid=kb%3Ben-us%3B175523&x=6&y=7
|
||||
|
||||
Also, even on non-Windows systems there may run a firewall or anti-virus
|
||||
software or similar that accepts the connection but does not actually do
|
||||
anything else. This will make (lib)curl to consider the connection connected
|
||||
and thus the connect timeout won't trigger.
|
||||
|
||||
|
||||
5. libcurl Issues
|
||||
|
||||
5.1 Is libcurl thread-safe?
|
||||
@@ -897,7 +916,7 @@ FAQ
|
||||
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
|
||||
http://www.openssl.org/docs/crypto/threads.html
|
||||
|
||||
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
|
||||
@@ -1158,7 +1177,7 @@ FAQ
|
||||
libraries that use it. It should be possible for everyone to use libcurl or
|
||||
curl in their projects, no matter what license they already have in use.
|
||||
|
||||
6.7 What are my obligations when using libcurl in my commerical apps?
|
||||
6.7 What are my obligations when using libcurl in my commercial apps?
|
||||
|
||||
Next to none. All you need to adhere to is the MIT-style license (stated in
|
||||
the COPYING file) which basically says you have to include the copyright
|
||||
@@ -1174,7 +1193,7 @@ FAQ
|
||||
your app.
|
||||
|
||||
As can be seen here: http://curl.haxx.se/docs/companies.html and
|
||||
elsewhere, more and more companies are dicovering the power
|
||||
elsewhere, more and more companies are discovering the power
|
||||
of libcurl and take advantage of it even in commercial environments.
|
||||
|
||||
|
||||
|
@@ -383,7 +383,7 @@ Win32
|
||||
- Modify lib/setup.h
|
||||
- Modify lib/Makefile.vc6
|
||||
- Add defines to Project/Settings/C/C++/General/Preprocessor Definitions
|
||||
in the curllib.dsw/curllib.dsp Visual C++ 6 IDE project.
|
||||
in the libcurl.dsw/libcurl.dsp Visual C++ 6 IDE project.
|
||||
|
||||
|
||||
Important static libcurl usage note
|
||||
|
@@ -42,11 +42,6 @@ may have been fixed since this was written!
|
||||
library header files exporting symbols/macros that should be kept private
|
||||
to the KfW library. See ticket #5601 at http://krbdev.mit.edu/rt/
|
||||
|
||||
53. SFTP busy-loop problem. When doing SFTP uploads, we can see that libcurl
|
||||
occasionally will busy-loop while waiting for certain network conditions.
|
||||
Reported by Pavel Shalagin, explained somewhat by Daniel Stenberg here:
|
||||
http://curl.haxx.se/mail/lib-2008-04/0439.html
|
||||
|
||||
52. Gautam Kachroo's issue that identifies a problem with the multi interface
|
||||
where a connection can be re-used without actually being properly
|
||||
SSL-negoatiated:
|
||||
@@ -64,13 +59,6 @@ may have been fixed since this was written!
|
||||
function will return prematurely and will confuse the rest of the HTTP
|
||||
protocol code. This should be very rare.
|
||||
|
||||
45. libcurl built to support ipv6 uses getaddrinfo() to resolve host names.
|
||||
getaddrinfo() sorts the response list which effectively kills how libcurl
|
||||
deals with round-robin DNS entries. All details:
|
||||
http://curl.haxx.se/mail/lib-2007-07/0168.html
|
||||
initial suggested function to use for randomizing the response:
|
||||
http://curl.haxx.se/mail/lib-2007-07/0178.html
|
||||
|
||||
43. There seems to be a problem when connecting to the Microsoft telnet server.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1720605
|
||||
|
||||
|
15
docs/MANUAL
15
docs/MANUAL
@@ -136,6 +136,14 @@ PROXY
|
||||
|
||||
curl -U user:passwd -x my-proxy:888 http://www.get.this/
|
||||
|
||||
A comma-separated list of hosts and domains which do not use the proxy can
|
||||
be specified as:
|
||||
|
||||
curl --noproxy localhost,get.this -x my-proxy:888 http://www.get.this/
|
||||
|
||||
If the proxy is specified with --proxy1.0 instead of --proxy or -x, then
|
||||
curl will use HTTP/1.0 instead of HTTP/1.1 for any CONNECT attempts.
|
||||
|
||||
curl also supports SOCKS4 and SOCKS5 proxies with --socks4 and --socks5.
|
||||
|
||||
See also the environment variables Curl support that offer further proxy
|
||||
@@ -504,7 +512,7 @@ CONFIG FILE
|
||||
can also specify the long options without the dashes to make it more
|
||||
readable. You can separate the options and the parameter with spaces, or
|
||||
with = or :. Comments can be used within the file. If the first letter on a
|
||||
line is a '#'-letter the rest of the line is treated as a comment.
|
||||
line is a '#'-symbol the rest of the line is treated as a comment.
|
||||
|
||||
If you want the parameter to contain spaces, you must enclose the entire
|
||||
parameter within double quotes ("). Within those quotes, you specify a
|
||||
@@ -793,8 +801,9 @@ ENVIRONMENT VARIABLES
|
||||
|
||||
NO_PROXY
|
||||
|
||||
If a tail substring of the domain-path for a host matches one of these
|
||||
strings, transactions with that node will not be proxied.
|
||||
If the host name matches one of these strings, or the host is within the
|
||||
domain of one of these strings, transactions with that node will not be
|
||||
proxied.
|
||||
|
||||
|
||||
The usage of the -x/--proxy flag overrides the environment variables.
|
||||
|
17
docs/THANKS
17
docs/THANKS
@@ -36,6 +36,7 @@ Andreas Ntaflos
|
||||
Andreas Olsson
|
||||
Andreas Rieke
|
||||
Andreas Schuldei
|
||||
Andreas Wurf
|
||||
Andres Garcia
|
||||
Andrew Benham
|
||||
Andrew Biggs
|
||||
@@ -44,11 +45,13 @@ Andrew Francis
|
||||
Andrew Fuller
|
||||
Andrew Moise
|
||||
Andrew Wansink
|
||||
Andrew de los Reyes
|
||||
Andr<EFBFBD>s Garc<72>a
|
||||
Andy Cedilnik
|
||||
Andy Serpa
|
||||
Andy Tsouladze
|
||||
Angus Mackay
|
||||
Anthony Bryan
|
||||
Antoine Calando
|
||||
Anton Kalmykov
|
||||
Arkadiusz Miskiewicz
|
||||
@@ -60,6 +63,7 @@ Augustus Saunders
|
||||
Avery Fay
|
||||
Axel Tillequin
|
||||
Bart Whiteley
|
||||
Bas Mevissen
|
||||
Ben Greear
|
||||
Ben Madsen
|
||||
Ben Van Hof
|
||||
@@ -90,6 +94,7 @@ Chris Combes
|
||||
Chris Flerackers
|
||||
Chris Gaukroger
|
||||
Chris Maltby
|
||||
Christian Krause
|
||||
Christian Kurz
|
||||
Christian Robottom Reis
|
||||
Christian Vogt
|
||||
@@ -210,6 +215,7 @@ Forrest Cahoon
|
||||
Frank Hempel
|
||||
Frank Keeney
|
||||
Frank Ticheler
|
||||
Fred Machado
|
||||
Fred New
|
||||
Fred Noz
|
||||
Frederic Lepied
|
||||
@@ -235,6 +241,7 @@ Giuseppe Attardi
|
||||
Giuseppe D'Ambrosio
|
||||
Glen Nakamura
|
||||
Glen Scott
|
||||
Grant Erickson
|
||||
Greg Hewgill
|
||||
Greg Morse
|
||||
Greg Onufer
|
||||
@@ -308,6 +315,7 @@ Jes Badwal
|
||||
Jesper Jensen
|
||||
Jesse Noller
|
||||
Jim Drash
|
||||
Jim Meyering
|
||||
Joe Halpin
|
||||
Joe Malicki
|
||||
Joel Chen
|
||||
@@ -330,6 +338,7 @@ Jonatan Lander
|
||||
Jonathan Hseu
|
||||
Jongki Suwandi
|
||||
Jose Kahan
|
||||
Josef Wolf
|
||||
Josh Kapell
|
||||
Juan F. Codagnone
|
||||
Juan Ignacio Herv<72>s
|
||||
@@ -356,6 +365,7 @@ Keith Mok
|
||||
Ken Hirsch
|
||||
Ken Rastatter
|
||||
Kent Boortz
|
||||
Keshav Krity
|
||||
Kevin Fisk
|
||||
Kevin Lussier
|
||||
Kevin Reed
|
||||
@@ -406,6 +416,7 @@ Mario Schroeder
|
||||
Mark Butler
|
||||
Mark Davies
|
||||
Mark Eichin
|
||||
Mark Karpeles
|
||||
Mark Lentczner
|
||||
Markus Koetter
|
||||
Markus Moeller
|
||||
@@ -496,11 +507,13 @@ Paul Querna
|
||||
Pavel Cenek
|
||||
Pavel Orehov
|
||||
Pawel A. Gajda
|
||||
Pawel Kierski
|
||||
Pedro Neves
|
||||
Pete Su
|
||||
Peter Bray
|
||||
Peter Forret
|
||||
Peter Heuchert
|
||||
Peter Korsgaard
|
||||
Peter Lamberg
|
||||
Peter O'Gorman
|
||||
Peter Pentchev
|
||||
@@ -513,6 +526,7 @@ Peter Wullinger
|
||||
Peteris Krumins
|
||||
Phil Blundell
|
||||
Phil Karn
|
||||
Phil Lisiecki
|
||||
Phil Pellouchoud
|
||||
Philip Gladstone
|
||||
Philip Langdale
|
||||
@@ -605,6 +619,7 @@ Spiridonoff A.V
|
||||
Stadler Stephan
|
||||
Stefan Esser
|
||||
Stefan Krause
|
||||
Stefan Teleman
|
||||
Stefan Ulrich
|
||||
Stephan Bergmann
|
||||
Stephen Collyer
|
||||
@@ -629,6 +644,7 @@ Thomas J. Moore
|
||||
Thomas Klausner
|
||||
Thomas Schwinge
|
||||
Thomas Tonino
|
||||
Tim Ansell
|
||||
Tim Baker
|
||||
Tim Bartley
|
||||
Tim Costello
|
||||
@@ -666,6 +682,7 @@ Vincent Bronner
|
||||
Vincent Le Normand
|
||||
Vincent Penquerc'h
|
||||
Vincent Sanders
|
||||
Vlad Grachov
|
||||
Vladimir Lazarenko
|
||||
Vojtech Janota
|
||||
Vojtech Minarik
|
||||
|
@@ -328,10 +328,10 @@ to provide the data to send.
|
||||
|
||||
8.1 Make NTLM work without OpenSSL functions
|
||||
|
||||
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++.
|
||||
Get NTLM working using the functions provided by NSS. 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++.
|
||||
|
||||
8.2 SSL engine stuff
|
||||
|
||||
|
66
docs/curl.1
66
docs/curl.1
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2009, 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
|
||||
@@ -292,6 +292,10 @@ traditional PORT command.
|
||||
|
||||
Since curl 7.19.0, \fB--eprt\fP can be used to explicitly enable EPRT again
|
||||
and \fB--no-eprt\fP is an alias for \fB--disable-eprt\fP.
|
||||
|
||||
Disabling EPRT only changes the active behavior. If you want to switch to
|
||||
passive mode you need to not use \fI-P/--ftp-port\fP or force it with
|
||||
\fI--ftp-pasv\fP.
|
||||
.IP "--disable-epsv"
|
||||
(FTP) Tell curl to disable the use of the EPSV command when doing passive FTP
|
||||
transfers. Curl will normally always first attempt to use EPSV before PASV,
|
||||
@@ -299,6 +303,9 @@ but with this option, it will not try using EPSV.
|
||||
|
||||
Since curl 7.19.0, \fB--epsv\fP can be used to explicitly enable EPRT again
|
||||
and \fB--no-epsv\fP is an alias for \fB--disable-epsv\fP.
|
||||
|
||||
Disabling EPSV only changes the passive behavior. If you want to switch to
|
||||
active mode you need to use \fI-P/--ftp-port\fP.
|
||||
.IP "-D/--dump-header <file>"
|
||||
Write the protocol headers to the specified file.
|
||||
|
||||
@@ -421,13 +428,16 @@ compliant than 'nocwd' but without the full penalty of 'multicwd'.
|
||||
.RE
|
||||
(Added in 7.15.1)
|
||||
.IP "--ftp-pasv"
|
||||
(FTP) Use PASV when transferring. PASV is the internal default behavior, but
|
||||
using this option can be used to override a previous --ftp-port option. (Added
|
||||
in 7.11.0)
|
||||
(FTP) Use passive mode for the data conection. Passive is the internal default
|
||||
behavior, but using this option can be used to override a previous
|
||||
\fI-P/-ftp-port\fP option. (Added in 7.11.0)
|
||||
|
||||
If this option is used several times, the following occurrences make no
|
||||
difference. Undoing an enforced PASV really isn't doable but you must then
|
||||
instead enforce the correct EPRT again.
|
||||
difference. Undoing an enforced passive really isn't doable but you must then
|
||||
instead enforce the correct \fI-P/--ftp-port\fP again.
|
||||
|
||||
Passive mode means that curl will try the EPSV command first and then PASV,
|
||||
unless \fI--disable-epsv\fP is used.
|
||||
.IP "--ftp-alternative-to-user <command>"
|
||||
(FTP) If authenticating with the USER and PASS commands fails, send this
|
||||
command. When connecting to Tumbleweed's Secure Transport server over FTPS
|
||||
@@ -815,6 +825,13 @@ you to succeed. (Added in 7.16.0)
|
||||
|
||||
Note that this is the negated option name documented. You can thus use
|
||||
\fI--sessionid\fP to enforce session-ID caching.
|
||||
.IP "--noproxy <no-proxy-list>"
|
||||
Comma-separated list of hosts which do not use a proxy, if one is specified.
|
||||
The only wildcard is a single * character, which matches all hosts, and
|
||||
effectively disables the proxy. Each name in this list is matched as either
|
||||
a domain which contains the hostname, or the hostname itself. For example,
|
||||
local.com would match local.com, local.com:80, and www.local.com, but not
|
||||
www.notlocal.com. (Added in 7.19.4).
|
||||
.IP "--ntlm"
|
||||
(HTTP) Enables NTLM authentication. The NTLM authentication method was
|
||||
designed by Microsoft and is used by IIS web servers. It is a proprietary
|
||||
@@ -846,7 +863,8 @@ or use several variables like:
|
||||
You may use this option as many times as the number of URLs you have.
|
||||
|
||||
See also the \fI--create-dirs\fP option to create the local directories
|
||||
dynamically.
|
||||
dynamically. Specifying the output as '-' (a single dash) will force the
|
||||
output to be done to stdout.
|
||||
.IP "-O/--remote-name"
|
||||
Write output to a local file named like the remote file we get. (Only the file
|
||||
part of the remote file is used, the path is cut off.)
|
||||
@@ -875,7 +893,7 @@ a redirection. This option is meaningful only when using \fI-L/--location\fP
|
||||
Tells curl to respect RFC 2616/10.3.2 and not convert POST requests into GET
|
||||
requests when following a 302 redirection. The non-RFC behaviour is ubiquitous
|
||||
in web browsers, so curl does the conversion by default to maintain
|
||||
consistency. However, a server may requires a POST to remain a POST after such
|
||||
consistency. However, a server may require a POST to remain a POST after such
|
||||
a redirection. This option is meaningful only when using \fI-L/--location\fP
|
||||
(Added in 7.19.1)
|
||||
.IP "--proxy-anyauth"
|
||||
@@ -896,6 +914,13 @@ with a remote host. (Added in 7.17.1)
|
||||
.IP "--proxy-ntlm"
|
||||
Tells curl to use HTTP NTLM authentication when communicating with the given
|
||||
proxy. Use \fI--ntlm\fP for enabling NTLM with a remote host.
|
||||
.IP "--proxy1.0 <proxyhost[:port]>"
|
||||
Use the specified HTTP 1.0 proxy. If the port number is not specified, it is
|
||||
assumed at port 1080.
|
||||
|
||||
The only difference between this and the HTTP proxy option (\fI-x/--proxy\fP),
|
||||
is that attempts to use CONNECT through the proxy will specify an HTTP 1.0
|
||||
protocol instead of the default HTTP 1.1.
|
||||
.IP "-p/--proxytunnel"
|
||||
When an HTTP proxy is used (\fI-x/--proxy\fP), this option will cause non-HTTP
|
||||
protocols to attempt to tunnel through the proxy instead of merely using it to
|
||||
@@ -908,11 +933,11 @@ separate file.
|
||||
|
||||
If this option is used several times, the last one will be used.
|
||||
.IP "-P/--ftp-port <address>"
|
||||
(FTP) Reverses the initiator/listener roles when connecting with FTP. This
|
||||
switch makes Curl use the PORT command instead of PASV. In practice, PORT
|
||||
tells the server to connect to the client's specified address and port, while
|
||||
PASV asks the server for an IP address and port to connect to. <address>
|
||||
should be one of:
|
||||
(FTP) Reverses the default initiator/listener roles when connecting with
|
||||
FTP. This switch makes curl use active mode. In practice, curl then tells the
|
||||
server to connect back to the client's specified address and port, while
|
||||
passive mode asks the server to setup an IP address and port for it to connect
|
||||
to. <address> should be one of:
|
||||
.RS
|
||||
.IP interface
|
||||
i.e "eth0" to specify which interface's IP address you want to use (Unix only)
|
||||
@@ -1107,6 +1132,21 @@ mutually exclusive.
|
||||
If this option is used several times, the last one will be used. (This option
|
||||
was previously wrongly documented and used as --socks without the number
|
||||
appended.)
|
||||
.IP "--socks5-gssapi-service <servicename>"
|
||||
The default service name for a socks server is rcmd/server-fqdn. This option
|
||||
allows you to change it.
|
||||
|
||||
Examples:
|
||||
--socks5 proxy-name \fI--socks5-gssapi-service\fP sockd would use
|
||||
sockd/proxy-name
|
||||
--socks5 proxy-name \fI--socks5-gssapi-service\fP sockd/real-name would use
|
||||
sockd/real-name for cases where the proxy-name does not match the princpal name.
|
||||
(Added in 7.19.4).
|
||||
.IP "--socks5-gssapi-nec"
|
||||
As part of the gssapi negotiation a protection mode is negotiated. The rfc1961
|
||||
says in section 4.3/4.4 it should be protected, but the NEC reference
|
||||
implementation does not. The option \fI--socks5-gssapi-nec\fP allows the
|
||||
unprotected exchange of the protection mode negotiation. (Added in 7.19.4).
|
||||
.IP "--stderr <file>"
|
||||
Redirect all writes to stderr to the specified file instead. If the file name
|
||||
is a plain '-', it is instead written to stdout. This option has no point when
|
||||
|
@@ -60,8 +60,8 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \
|
||||
|
||||
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
||||
|
||||
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4 ABI
|
||||
|
||||
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4 ABI \
|
||||
symbols-in-versions
|
||||
MAN2HTML= roffit --mandir=. < $< >$@
|
||||
|
||||
SUFFIXES = .3 .html
|
||||
|
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2009, 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
|
||||
@@ -21,7 +21,7 @@
|
||||
.\" * $Id$
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_easy_getinfo 3 "16 Oct 2008" "libcurl 7.19.1" "libcurl Manual"
|
||||
.TH curl_easy_getinfo 3 "11 Feb 2009" "libcurl 7.19.4" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_easy_getinfo - extract information from a curl handle
|
||||
.SH SYNOPSIS
|
||||
@@ -134,9 +134,11 @@ on the list pointer once you're done with it, as libcurl will not free the
|
||||
data for you. (Added in 7.12.3)
|
||||
.IP CURLINFO_CONTENT_LENGTH_DOWNLOAD
|
||||
Pass a pointer to a double to receive the content-length of the download. This
|
||||
is the value read from the Content-Length: field.
|
||||
is the value read from the Content-Length: field. Since 7.19.4, this returns -1
|
||||
if the size isn't known.
|
||||
.IP CURLINFO_CONTENT_LENGTH_UPLOAD
|
||||
Pass a pointer to a double to receive the specified size of the upload.
|
||||
Pass a pointer to a double to receive the specified size of the upload. Since
|
||||
7.19.4, this returns -1 if the size isn't known.
|
||||
.IP CURLINFO_CONTENT_TYPE
|
||||
Pass a pointer to a 'char *' to receive the content-type of the downloaded
|
||||
object. This is the value read from the Content-Type: field. If you get NULL,
|
||||
@@ -200,6 +202,12 @@ provided in a series of data in the format "name:content" where the content is
|
||||
for the specific named data. See also the certinfo.c example. NOTE: this
|
||||
option is only available in libcurl built with OpenSSL support. (Added in
|
||||
7.19.1)
|
||||
.IP CURLINFO_CONDITION_UNMET
|
||||
Pass a pointer to a long to receive the number 1 if the condition provided in
|
||||
the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if
|
||||
this returns a 1 you know that the reason you didn't get data in return is
|
||||
because it didn't fulfill the condition. The long ths argument points to will
|
||||
get a zero stored if the condition instead was met. (Added in 7.19.4)
|
||||
.SH TIMES
|
||||
.NF
|
||||
An overview of the six time values available from curl_easy_getinfo()
|
||||
|
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2009, 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
|
||||
@@ -440,12 +440,33 @@ The string given to CURLOPT_URL must be url-encoded and follow RFC 2396
|
||||
|
||||
\fICURLOPT_URL\fP is the only option that \fBmust\fP be set before
|
||||
\fIcurl_easy_perform(3)\fP is called.
|
||||
|
||||
\fICURLOPT_PROTOCOLS\fP can be used to limit what protocols libcurl will use
|
||||
for this transfer, independent of what libcurl has been compiled to
|
||||
support. That may be useful if you accept the URL from an external source and
|
||||
want to limit the accessibility.
|
||||
.IP CURLOPT_PROTOCOLS
|
||||
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
|
||||
limits what protocols libcurl may use in the transfer. This allows you to have
|
||||
a libcurl built to support a wide range of protocols but still limit specific
|
||||
transfers to only be allowed to use a subset of them. By default libcurl will
|
||||
accept all protocols it supports. See also
|
||||
\fICURLOPT_REDIR_PROTOCOLS\fP. (Added in 7.19.4)
|
||||
.IP CURLOPT_REDIR_PROTOCOLS
|
||||
Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
|
||||
limits what protocols libcurl may use in a transfer that it follows to in a
|
||||
redirect when \fICURLOPT_FOLLOWLOCATION\fP is enabled. This allows you to
|
||||
limit specific transfers to only be allowed to use a subset of protocols in
|
||||
redirections. By default libcurl will allow all protocols except for FILE and
|
||||
SCP. This is a difference compared to pre-7.19.4 versions which
|
||||
unconditionally would follow to all protocols supported. (Added in 7.19.4)
|
||||
.IP CURLOPT_PROXY
|
||||
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
|
||||
string holding the host name or dotted IP address. To specify port number in
|
||||
this string, append :[port] to the end of the host name. The proxy string may
|
||||
be prefixed with [protocol]:// since any such prefix will be ignored. The
|
||||
proxy's port number may optionally be specified with the separate option
|
||||
proxy's port number may optionally be specified with the separate option. If
|
||||
not specified, libcurl will default to using port 1080 for proxies.
|
||||
\fICURLOPT_PROXYPORT\fP.
|
||||
|
||||
When you tell the library to use an HTTP proxy, libcurl will transparently
|
||||
@@ -470,15 +491,33 @@ Pass a long with this option to set the proxy port to connect to unless it is
|
||||
specified in the proxy string \fICURLOPT_PROXY\fP.
|
||||
.IP CURLOPT_PROXYTYPE
|
||||
Pass a long with this option to set type of the proxy. Available options for
|
||||
this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_SOCKS4\fP (added in 7.15.2),
|
||||
\fICURLPROXY_SOCKS5\fP, \fICURLPROXY_SOCKS4A\fP (added in 7.18.0) and
|
||||
\fICURLPROXY_SOCKS5_HOSTNAME\fP (added in 7.18.0). The HTTP type is
|
||||
default. (Added in 7.10)
|
||||
this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_HTTP_1_0\fP (added in 7.19.4),
|
||||
\fICURLPROXY_SOCKS4\fP (added in 7.15.2), \fICURLPROXY_SOCKS5\fP,
|
||||
\fICURLPROXY_SOCKS4A\fP (added in 7.18.0) and \fICURLPROXY_SOCKS5_HOSTNAME\fP
|
||||
(added in 7.18.0). The HTTP type is default. (Added in 7.10)
|
||||
.IP CURLOPT_NOPROXY
|
||||
Pass a pointer to a zero terminated string. The should be a comma- separated
|
||||
list of hosts which do not use a proxy, if one is specified. The only
|
||||
wildcard is a single * character, which matches all hosts, and effectively
|
||||
disables the proxy. Each name in this list is matched as either a domain which
|
||||
contains the hostname, or the hostname itself. For example, local.com would
|
||||
match local.com, local.com:80, and www.local.com, but not www.notlocal.com.
|
||||
(Added in 7.19.4)
|
||||
.IP CURLOPT_HTTPPROXYTUNNEL
|
||||
Set the parameter to 1 to make the library tunnel all operations through a
|
||||
given HTTP proxy. There is a big difference between using a proxy and to
|
||||
tunnel through it. If you don't know what this means, you probably don't want
|
||||
this tunneling option.
|
||||
.IP CURLOPT_SOCKS5_GSSAPI_SERVICE
|
||||
Pass a char * as parameter to a string holding the name of the service. The
|
||||
default service name for a SOCKS5 server is rcmd/server-fqdn. This option
|
||||
allows you to change it. (Added in 7.19.4)
|
||||
.IP CURLOPT_SOCKS5_GSSAPI_NEC
|
||||
Pass a long set to 1 to enable or 0 to disable. As part of the gssapi
|
||||
negotiation a protection mode is negotiated. The rfc1961 says in section
|
||||
4.3/4.4 it should be protected, but the NEC reference implementation does not.
|
||||
If enabled, this option allows the unprotected exchange of the protection mode
|
||||
negotiation. (Added in 7.19.4).
|
||||
.IP CURLOPT_INTERFACE
|
||||
Pass a char * as parameter. This sets the interface name to use as outgoing
|
||||
network interface. The name can be an interface name, an IP address, or a host
|
||||
@@ -545,7 +584,7 @@ data at a time, and can contribute to congestion on the network if
|
||||
overdone.
|
||||
.IP CURLOPT_ADDRESS_SCOPE
|
||||
Pass a long specifying the scope_id value to use when connecting to IPv6
|
||||
link-local or site-local addresses.
|
||||
link-local or site-local addresses. (Added in 7.19.0)
|
||||
.SH NAMES and PASSWORDS OPTIONS (Authentication)
|
||||
.IP CURLOPT_NETRC
|
||||
This parameter controls the preference of libcurl between using user names and
|
||||
@@ -724,6 +763,10 @@ This means that the library will re-send the same request on the new location
|
||||
and follow new Location: headers all the way until no more such headers are
|
||||
returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
|
||||
libcurl will follow.
|
||||
|
||||
NOTE: since 7.19.4, libcurl can limit to what protocols it will automatically
|
||||
follow. The accepted protocols are set with \fICURLOPT_REDIR_PROTOCOLS\fP and
|
||||
it excludes the FILE protocol by default.
|
||||
.IP CURLOPT_UNRESTRICTED_AUTH
|
||||
A parameter set to 1 tells the library it can continue to send authentication
|
||||
(user+password) when following locations, even when hostname changed. This
|
||||
@@ -843,7 +886,6 @@ copy. In any case, the size must not be changed after
|
||||
\fICURLOPT_COPYPOSTFIELDS\fP, unless another \fICURLOPT_POSTFIELDS\fP or
|
||||
\fICURLOPT_COPYPOSTFIELDS\fP option is issued.
|
||||
(Added in 7.17.1)
|
||||
|
||||
.IP CURLOPT_HTTPPOST
|
||||
Tells libcurl you want a multipart/formdata HTTP POST to be made and you
|
||||
instruct what data to pass on to the server. Pass a pointer to a linked list
|
||||
@@ -1000,6 +1042,14 @@ Pass a long to tell libcurl how to act on transfer decoding. If set to zero,
|
||||
transfer decoding will be disabled, if set to 1 it is enabled
|
||||
(default). libcurl does chunked transfer decoding by default unless this
|
||||
option is set to zero. (added in 7.16.2)
|
||||
.SH TFTP OPTIONS
|
||||
.IP CURLOPT_TFTPBLKSIZE
|
||||
Specify block size to use for TFTP data transmission. Valid range as per RFC
|
||||
2348 is 8-65464 bytes. The default of 512 bytes will be used if this option is
|
||||
not specified. The specified block size will only be used pending support by
|
||||
the remote server. If the server does not return an option acknowledgement or
|
||||
returns an option acknowledgement with no blksize, the default of 512 bytes
|
||||
will be used. (added in 7.19.4)
|
||||
.SH FTP OPTIONS
|
||||
.IP CURLOPT_FTPPORT
|
||||
Pass a pointer to a zero terminated string as parameter. It will be used to
|
||||
@@ -1078,6 +1128,17 @@ This setting also applies to SFTP-connections. curl will attempt to create
|
||||
the remote directory if it can't obtain a handle to the target-location. The
|
||||
creation will fail if a file of the same name as the directory to create
|
||||
already exists or lack of permissions prevents creation. (Added in 7.16.3)
|
||||
|
||||
Starting with 7.19.4, you can also set this value to 2, which will make
|
||||
libcurl retry the CWD command again if the subsequent MKD command fails. This
|
||||
is especially useful if you're doing many simultanoes connections against the
|
||||
same server and they all have this option enabled, as then CWD may first fail
|
||||
but then another connection does MKD before this connection and thus MKD fails
|
||||
but trying CWD works! 7.19.4 also introduced the \fICURLFTP_CREATE_DIR\fP and
|
||||
\fICURLFTP_CREATE_DIR_RETRY\fP enum names for these arguments.
|
||||
|
||||
Before version 7.19.4, libcurl will simply ignore arguments set to 2 and act
|
||||
as if 1 was selected.
|
||||
.IP CURLOPT_FTP_RESPONSE_TIMEOUT
|
||||
Pass a long. Causes curl to set a timeout period (in seconds) on the amount
|
||||
of time that the server is allowed to take in order to generate a response
|
||||
@@ -1164,6 +1225,7 @@ libcurl does one CWD with the full target directory and then operates on the
|
||||
file \&"normally" (like in the multicwd case). This is somewhat more standards
|
||||
compliant than 'nocwd' but without the full penalty of 'multicwd'.
|
||||
.RE
|
||||
(Added in 7.15.1)
|
||||
.SH PROTOCOL OPTIONS
|
||||
.IP CURLOPT_TRANSFERTEXT
|
||||
A parameter set to 1 tells the library to use ASCII mode for FTP transfers,
|
||||
@@ -1300,8 +1362,10 @@ value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
|
||||
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
|
||||
|
||||
The last modification time of a file is not always known and in such instances
|
||||
this feature will have no effect even if the given time condition would not have
|
||||
been met.
|
||||
this feature will have no effect even if the given time condition would not
|
||||
have been met. \fIcurl_easy_getinfo(3)\fP with the
|
||||
\fICURLINFO_CONDITION_UNMET\fP option can be used after a transfer to learn if
|
||||
a zero-byte successful "transfer" was due to this condition not matching.
|
||||
.IP CURLOPT_TIMEVALUE
|
||||
Pass a long as parameter. This should be the time in seconds since 1 Jan 1970,
|
||||
and the time will be used in a condition as specified with
|
||||
|
314
docs/libcurl/symbols-in-versions
Normal file
314
docs/libcurl/symbols-in-versions
Normal file
@@ -0,0 +1,314 @@
|
||||
_ _ ____ _
|
||||
___| | | | _ \| |
|
||||
/ __| | | | |_) | |
|
||||
| (__| |_| | _ <| |___
|
||||
\___|\___/|_| \_\_____|
|
||||
|
||||
This document lists defines and other symbols present in libcurl, together
|
||||
with exact information about the first libcurl version that provides the
|
||||
symbol, the first version in which the symbol was marked as deprecated and
|
||||
for a few symbols the last version that featured it. The names appear in
|
||||
alphabetical order.
|
||||
|
||||
Name Introduced Deprecated Removed
|
||||
|
||||
CURLAUTH_ANY 7.10.6
|
||||
CURLAUTH_ANYSAFE 7.10.6
|
||||
CURLAUTH_BASIC 7.10.6
|
||||
CURLAUTH_DIGEST 7.10.6
|
||||
CURLAUTH_DIGEST_IE 7.19.3
|
||||
CURLAUTH_GSSNEGOTIATE 7.10.6
|
||||
CURLAUTH_NTLM 7.10.6
|
||||
CURLFTPAUTH_DEFAULT 7.12.2
|
||||
CURLFTPAUTH_DEFAULT 7.12.2
|
||||
CURLFTPAUTH_SSL 7.12.2
|
||||
CURLFTPAUTH_SSL 7.12.2
|
||||
CURLFTPAUTH_TLS 7.12.2
|
||||
CURLFTPAUTH_TLS 7.12.2
|
||||
CURLFTPMETHOD_MULTICWD 7.15.1
|
||||
CURLFTPMETHOD_NOCWD 7.15.1
|
||||
CURLFTPMETHOD_SINGLECWD 7.15.1
|
||||
CURLFTPSSL_CCC_ACTIVE 7.16.1
|
||||
CURLFTPSSL_CCC_NONE 7.16.1
|
||||
CURLFTPSSL_CCC_PASSIVE 7.16.1
|
||||
CURLFTP_CREATE_DIR 7.19.4
|
||||
CURLFTP_CREATE_DIR_NONE 7.19.4
|
||||
CURLFTP_CREATE_DIR_RETRY 7.19.4
|
||||
CURLINFO_APPCONNECT_TIME 7.19.0
|
||||
CURLINFO_CERTINFO 7.19.1
|
||||
CURLINFO_CONDITION_UNMET 7.19.4
|
||||
CURLINFO_CONNECT_TIME 7.4.1
|
||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD 7.6.1
|
||||
CURLINFO_CONTENT_LENGTH_UPLOAD 7.6.1
|
||||
CURLINFO_CONTENT_TYPE 7.9.4
|
||||
CURLINFO_COOKIELIST 7.14.1
|
||||
CURLINFO_DATA_IN 7.9.6
|
||||
CURLINFO_DATA_OUT 7.9.6
|
||||
CURLINFO_FILETIME 7.5
|
||||
CURLINFO_FTP_ENTRY_PATH 7.15.4
|
||||
CURLINFO_HEADER_IN 7.9.6
|
||||
CURLINFO_HEADER_OUT 7.9.6
|
||||
CURLINFO_HEADER_SIZE 7.4.1
|
||||
CURLINFO_HTTPAUTH_AVAIL 7.10.8
|
||||
CURLINFO_HTTP_CODE 7.4.1 7.10.8
|
||||
CURLINFO_HTTP_CONNECTCODE 7.10.7
|
||||
CURLINFO_LASTSOCKET 7.15.2
|
||||
CURLINFO_NAMELOOKUP_TIME 7.4.1
|
||||
CURLINFO_NUM_CONNECTS 7.12.3
|
||||
CURLINFO_OS_ERRNO 7.12.2
|
||||
CURLINFO_PRETRANSFER_TIME 7.4.1
|
||||
CURLINFO_PRIMARY_IP 7.19.0
|
||||
CURLINFO_PRIVATE 7.10.3
|
||||
CURLINFO_PRIVATE 7.10.3
|
||||
CURLINFO_PROXYAUTH_AVAIL 7.10.8
|
||||
CURLINFO_REDIRECT_COUNT 7.9.7
|
||||
CURLINFO_REDIRECT_TIME 7.9.7
|
||||
CURLINFO_REDIRECT_URL 7.18.2
|
||||
CURLINFO_REQUEST_SIZE 7.4.1
|
||||
CURLINFO_RESPONSE_CODE 7.10.8
|
||||
CURLINFO_SIZE_DOWNLOAD 7.4.1
|
||||
CURLINFO_SIZE_UPLOAD 7.4.1
|
||||
CURLINFO_SPEED_DOWNLOAD 7.4.1
|
||||
CURLINFO_SPEED_UPLOAD 7.4.1
|
||||
CURLINFO_SSL_ENGINES 7.12.3
|
||||
CURLINFO_SSL_VERIFYRESULT 7.5
|
||||
CURLINFO_STARTTRANSFER_TIME 7.9.2
|
||||
CURLINFO_TEXT 7.9.6
|
||||
CURLINFO_TOTAL_TIME 7.4.1
|
||||
CURLOPT_ADDRESS_SCOPE 7.19.0
|
||||
CURLOPT_APPEND 7.16.4
|
||||
CURLOPT_AUTOREFERER 7.1
|
||||
CURLOPT_BUFFERSIZE 7.10
|
||||
CURLOPT_CAINFO 7.4.2
|
||||
CURLOPT_CAPATH 7.9.8
|
||||
CURLOPT_CERTINFO 7.19.1
|
||||
CURLOPT_CLOSEFUNCTION 7.7 7.11.1 7.15.4
|
||||
CURLOPT_CLOSEPOLICY 7.7 7.16.1
|
||||
CURLOPT_CONNECTTIMEOUT 7.7
|
||||
CURLOPT_CONNECTTIMEOUT_MS 7.16.2
|
||||
CURLOPT_CONNECT_ONLY 7.15.2
|
||||
CURLOPT_CONV_FROM_NETWORK_FUNCTION 7.15.4
|
||||
CURLOPT_CONV_FROM_UTF8_FUNCTION 7.15.4
|
||||
CURLOPT_CONV_TO_NETWORK_FUNCTION 7.15.4
|
||||
CURLOPT_COOKIE 7.1
|
||||
CURLOPT_COOKIEFILE 7.1
|
||||
CURLOPT_COOKIEJAR 7.9
|
||||
CURLOPT_COOKIELIST 7.17.1
|
||||
CURLOPT_COOKIESESSION 7.9.7
|
||||
CURLOPT_COPYPOSTFIELDS 7.17.1
|
||||
CURLOPT_CRLF 7.1
|
||||
CURLOPT_CRLFILE 7.19.0
|
||||
CURLOPT_CUSTOMREQUEST 7.1
|
||||
CURLOPT_DEBUGDATA 7.9.6
|
||||
CURLOPT_DEBUGFUNCTION 7.9.6
|
||||
CURLOPT_DIRLISTONLY 7.16.4
|
||||
CURLOPT_DNS_CACHE_TIMEOUT 7.9.3
|
||||
CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1
|
||||
CURLOPT_EGDSOCKET 7.7
|
||||
CURLOPT_ENCODING 7.12.2
|
||||
CURLOPT_ERRORBUFFER 7.1
|
||||
CURLOPT_FAILONERROR 7.1
|
||||
CURLOPT_FILE 7.1 7.9.7
|
||||
CURLOPT_FILETIME 7.5
|
||||
CURLOPT_FLAGS 7.1 - 7.9.2
|
||||
CURLOPT_FOLLOWLOCATION 7.1
|
||||
CURLOPT_FORBID_REUSE 7.7
|
||||
CURLOPT_FRESH_CONNECT 7.7
|
||||
CURLOPT_FTPAPPEND 7.1 7.16.4
|
||||
CURLOPT_FTPASCII 7.1 7.11.1 7.15.4
|
||||
CURLOPT_FTPLISTONLY 7.1 7.16.4
|
||||
CURLOPT_FTPPORT 7.1
|
||||
CURLOPT_FTPSSLAUTH 7.12.2
|
||||
CURLOPT_FTP_ACCOUNT 7.13.1
|
||||
CURLOPT_FTP_ALTERNATIVE_TO_USER 7.15.5
|
||||
CURLOPT_FTP_CREATE_MISSING_DIRS 7.10.7
|
||||
CURLOPT_FTP_FILEMETHOD 7.15.1
|
||||
CURLOPT_FTP_RESPONSE_TIMEOUT 7.10.8
|
||||
CURLOPT_FTP_SKIP_PASV_IP 7.15.0
|
||||
CURLOPT_FTP_SSL 7.11.0 7.16.4
|
||||
CURLOPT_FTP_SSL_CCC 7.16.1
|
||||
CURLOPT_FTP_USE_EPRT 7.10.5
|
||||
CURLOPT_FTP_USE_EPSV 7.9.2
|
||||
CURLOPT_HEADER 7.1
|
||||
CURLOPT_HEADERFUNCTION 7.7.2
|
||||
CURLOPT_HTTP200ALIASES 7.10.3
|
||||
CURLOPT_HTTPAUTH 7.10.6
|
||||
CURLOPT_HTTPGET 7.8.1
|
||||
CURLOPT_HTTPHEADER 7.1
|
||||
CURLOPT_HTTPPOST 7.1
|
||||
CURLOPT_HTTPPROXYTUNNEL 7.3
|
||||
CURLOPT_HTTPREQUEST 7.1 - 7.15.4
|
||||
CURLOPT_HTTP_CONTENT_DECODING 7.16.2
|
||||
CURLOPT_HTTP_TRANSFER_DECODING 7.16.2
|
||||
CURLOPT_HTTP_VERSION 7.9.1
|
||||
CURLOPT_IGNORE_CONTENT_LENGTH 7.14.1
|
||||
CURLOPT_INFILE 7.1 7.9.7
|
||||
CURLOPT_INFILESIZE 7.1
|
||||
CURLOPT_INFILESIZE_LARGE 7.11.0
|
||||
CURLOPT_INTERFACE 7.3
|
||||
CURLOPT_IOCTLDATA 7.12.3
|
||||
CURLOPT_IOCTLFUNCTION 7.12.3
|
||||
CURLOPT_IPRESOLVE 7.10.8
|
||||
CURLOPT_ISSUERCERT 7.19.0
|
||||
CURLOPT_KEYPASSWD 7.17.0
|
||||
CURLOPT_KRB4LEVEL 7.3
|
||||
CURLOPT_KRBLEVEL 7.16.4
|
||||
CURLOPT_LOCALPORT 7.15.2
|
||||
CURLOPT_LOCALPORTRANGE 7.15.2
|
||||
CURLOPT_LOW_SPEED_LIMIT 7.1
|
||||
CURLOPT_LOW_SPEED_TIME 7.1
|
||||
CURLOPT_MAXCONNECTS 7.7
|
||||
CURLOPT_MAXFILESIZE 7.10.8
|
||||
CURLOPT_MAXFILESIZE_LARGE 7.11.0
|
||||
CURLOPT_MAXREDIRS 7.5
|
||||
CURLOPT_MAX_RECV_SPEED_LARGE 7.15.5
|
||||
CURLOPT_MAX_SEND_SPEED_LARGE 7.15.5
|
||||
CURLOPT_MUTE 7.1 7.8 7.15.4
|
||||
CURLOPT_NETRC 7.1
|
||||
CURLOPT_NETRC_FILE 7.11.0
|
||||
CURLOPT_NEW_DIRECTORY_PERMS 7.16.4
|
||||
CURLOPT_NEW_FILE_PERMS 7.16.4
|
||||
CURLOPT_NOBODY 7.1
|
||||
CURLOPT_NOPROGRESS 7.1
|
||||
CURLOPT_NOPROXY 7.19.4
|
||||
CURLOPT_NOSIGNAL 7.10
|
||||
CURLOPT_OPENSOCKETDATA 7.17.1
|
||||
CURLOPT_OPENSOCKETFUNCTION 7.17.1
|
||||
CURLOPT_PASSWDDATA 7.1 7.11.1 7.15.4
|
||||
CURLOPT_PASSWDFUNCTION 7.1 7.11.1 7.15.4
|
||||
CURLOPT_PASSWORD 7.19.1
|
||||
CURLOPT_PASV_POST 7.12.1 - 7.13.0
|
||||
CURLOPT_PORT 7.1
|
||||
CURLOPT_POST 7.1
|
||||
CURLOPT_POST301 7.17.1 7.19.1
|
||||
CURLOPT_POSTFIELDS 7.1
|
||||
CURLOPT_POSTFIELDSIZE 7.2
|
||||
CURLOPT_POSTFIELDSIZE_LARGE 7.11.1
|
||||
CURLOPT_POSTQUOTE 7.1
|
||||
CURLOPT_POSTREDIR 7.19.1
|
||||
CURLOPT_PREQUOTE 7.9.5
|
||||
CURLOPT_PRIVATE 7.10.3
|
||||
CURLOPT_PROGRESSDATA 7.1
|
||||
CURLOPT_PROGRESSFUNCTION 7.1
|
||||
CURLOPT_PROGRESSMODE 7.1 - 7.9.2
|
||||
CURLOPT_PROTOCOLS 7.19.4
|
||||
CURLOPT_PROXY 7.1
|
||||
CURLOPT_PROXYAUTH 7.10.7
|
||||
CURLOPT_PROXYPASSWORD 7.19.1
|
||||
CURLOPT_PROXYPORT 7.1
|
||||
CURLOPT_PROXYTYPE 7.10
|
||||
CURLOPT_PROXYUSERNAME 7.19.1
|
||||
CURLOPT_PROXYUSERPWD 7.1
|
||||
CURLOPT_PROXY_TRANSFER_MODE 7.18.0
|
||||
CURLOPT_PUT 7.1
|
||||
CURLOPT_QUOTE 7.1
|
||||
CURLOPT_RANDOM_FILE 7.7
|
||||
CURLOPT_RANGE 7.1
|
||||
CURLOPT_READDATA 7.9.7
|
||||
CURLOPT_READFUNCTION 7.1
|
||||
CURLOPT_REDIR_PROTOCOLS 7.19.4
|
||||
CURLOPT_REFERER 7.1
|
||||
CURLOPT_RESUME_FROM 7.1
|
||||
CURLOPT_RESUME_FROM_LARGE 7.11.0
|
||||
CURLOPT_SEEKDATA 7.18.1
|
||||
CURLOPT_SEEKFUNCTION 7.18.1
|
||||
CURLOPT_SHARE 7.10
|
||||
CURLOPT_SOCKOPTDATA 7.16.0
|
||||
CURLOPT_SOCKOPTFUNCTION 7.16.0
|
||||
CURLOPT_SOCKS5_GSSAPI_NEC 7.19.4
|
||||
CURLOPT_SOCKS5_GSSAPI_SERVICE 7.19.4
|
||||
CURLOPT_SOURCE_HOST 7.12.1 - 7.13.0
|
||||
CURLOPT_SOURCE_PATH 7.12.1 - 7.13.0
|
||||
CURLOPT_SOURCE_PORT 7.12.1 - 7.13.0
|
||||
CURLOPT_SOURCE_POSTQUOTE 7.12.1 - 7.15.4
|
||||
CURLOPT_SOURCE_PREQUOTE 7.12.1 - 7.15.4
|
||||
CURLOPT_SOURCE_QUOTE 7.13.0 - 7.15.4
|
||||
CURLOPT_SOURCE_URL 7.13.0 - 7.15.4
|
||||
CURLOPT_SOURCE_USERPWD 7.12.1 - 7.15.4
|
||||
CURLOPT_SSH_AUTH_TYPES 7.16.1
|
||||
CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 7.17.1
|
||||
CURLOPT_SSH_PRIVATE_KEYFILE 7.16.1
|
||||
CURLOPT_SSH_PUBLIC_KEYFILE 7.16.1
|
||||
CURLOPT_SSLCERT 7.1
|
||||
CURLOPT_SSLCERTTYPE 7.9.3
|
||||
CURLOPT_SSLENGINE 7.9.3
|
||||
CURLOPT_SSLENGINE_DEFAULT 7.9.3
|
||||
CURLOPT_SSLKEY 7.9.3
|
||||
CURLOPT_SSLKEYPASSWD 7.17.0
|
||||
CURLOPT_SSLKEYTYPE 7.9.3
|
||||
CURLOPT_SSLVERSION 7.1
|
||||
CURLOPT_SSL_CIPHER_LIST 7.9
|
||||
CURLOPT_SSL_CTX_DATA 7.10.6
|
||||
CURLOPT_SSL_CTX_FUNCTION 7.10.6
|
||||
CURLOPT_SSL_SESSIONID_CACHE 7.16.0
|
||||
CURLOPT_SSL_VERIFYHOST 7.8.1
|
||||
CURLOPT_SSL_VERIFYPEER 7.4.2
|
||||
CURLOPT_STDERR 7.1
|
||||
CURLOPT_TCP_NODELAY 7.11.2
|
||||
CURLOPT_TELNETOPTIONS 7.7
|
||||
CURLOPT_TFTPBLKSIZE 7.19.4
|
||||
CURLOPT_TIMECONDITION 7.1
|
||||
CURLOPT_TIMEOUT 7.1
|
||||
CURLOPT_TIMEOUT_MS 7.16.2
|
||||
CURLOPT_TIMEVALUE 7.1
|
||||
CURLOPT_TRANSFERTEXT 7.11.1
|
||||
CURLOPT_UNRESTRICTED_AUTH 7.10.4
|
||||
CURLOPT_UPLOAD 7.1
|
||||
CURLOPT_URL 7.1
|
||||
CURLOPT_USERAGENT 7.1
|
||||
CURLOPT_USERNAME 7.19.1
|
||||
CURLOPT_USERPWD 7.1
|
||||
CURLOPT_USE_SSL 7.17.0
|
||||
CURLOPT_VERBOSE 7.1
|
||||
CURLOPT_WRITEDATA 7.9.7
|
||||
CURLOPT_WRITEFUNCTION 7.1
|
||||
CURLOPT_WRITEHEADER 7.1
|
||||
CURLPROTO_ALL 7.19.4
|
||||
CURLPROTO_DICT 7.19.4
|
||||
CURLPROTO_FILE 7.19.4
|
||||
CURLPROTO_FTP 7.19.4
|
||||
CURLPROTO_FTPS 7.19.4
|
||||
CURLPROTO_HTTP 7.19.4
|
||||
CURLPROTO_HTTPS 7.19.4
|
||||
CURLPROTO_LDAP 7.19.4
|
||||
CURLPROTO_LDAPS 7.19.4
|
||||
CURLPROTO_SCP 7.19.4
|
||||
CURLPROTO_SFTP 7.19.4
|
||||
CURLPROTO_TELNET 7.19.4
|
||||
CURLPROTO_TFTP 7.19.4
|
||||
CURLPROXY_HTTP 7.10
|
||||
CURLPROXY_HTTP_1_0 7.19.4
|
||||
CURLPROXY_SOCKS4 7.10
|
||||
CURLPROXY_SOCKS4A 7.18.0
|
||||
CURLPROXY_SOCKS5 7.10
|
||||
CURLPROXY_SOCKS5_HOSTNAME 7.18.0
|
||||
CURLUSESSL_ALL 7.17.0
|
||||
CURLUSESSL_CONTROL 7.17.0
|
||||
CURLUSESSL_NONE 7.17.0
|
||||
CURLUSESSL_TRY 7.17.0
|
||||
CURL_HTTP_VERSION_1_0 7.9.1
|
||||
CURL_HTTP_VERSION_1_1 7.9.1
|
||||
CURL_HTTP_VERSION_NONE 7.9.1
|
||||
CURL_IPRESOLVE_V4 7.10.8
|
||||
CURL_IPRESOLVE_V6 7.10.8
|
||||
CURL_IPRESOLVE_WHATEVER 7.10.8
|
||||
CURL_NETRC_IGNORED 7.9.8
|
||||
CURL_NETRC_OPTIONAL 7.9.8
|
||||
CURL_NETRC_REQUIRED 7.9.8
|
||||
CURL_SSLVERSION_DEFAULT 7.9.2
|
||||
CURL_SSLVERSION_SSLv2 7.9.2
|
||||
CURL_SSLVERSION_SSLv3 7.9.2
|
||||
CURL_SSLVERSION_TLSv1 7.9.2
|
||||
CURL_VERSION_ASYNCHDNS 7.10.7
|
||||
CURL_VERSION_CONV 7.15.4
|
||||
CURL_VERSION_DEBUG 7.10.6
|
||||
CURL_VERSION_GSSNEGOTIATE 7.10.6
|
||||
CURL_VERSION_IDN 7.12.0
|
||||
CURL_VERSION_IPV6 7.10
|
||||
CURL_VERSION_KERBEROS4 7.10
|
||||
CURL_VERSION_LARGEFILE 7.11.1
|
||||
CURL_VERSION_LIBZ 7.10
|
||||
CURL_VERSION_NTLM 7.10.6
|
||||
CURL_VERSION_SPNEGO 7.10.8
|
||||
CURL_VERSION_SSL 7.10
|
||||
CURL_VERSION_SSPI 7.13.2
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -459,7 +459,10 @@ typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
|
||||
void *userptr);
|
||||
|
||||
typedef enum {
|
||||
CURLPROXY_HTTP = 0, /* added in 7.10 */
|
||||
CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use
|
||||
CONNECT HTTP/1.1 */
|
||||
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
|
||||
HTTP/1.0 */
|
||||
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
|
||||
in 7.10 */
|
||||
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
|
||||
@@ -527,6 +530,17 @@ typedef enum {
|
||||
CURLFTPAUTH_LAST /* not an option, never use */
|
||||
} curl_ftpauth;
|
||||
|
||||
/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
|
||||
typedef enum {
|
||||
CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */
|
||||
CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD
|
||||
again if MKD succeeded, for SFTP this does
|
||||
similar magic */
|
||||
CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
|
||||
again even if MKD failed! */
|
||||
CURLFTP_CREATE_DIR_LAST /* not an option, never use */
|
||||
} curl_ftpcreatedir;
|
||||
|
||||
/* parameter for the CURLOPT_FTP_FILEMETHOD option */
|
||||
typedef enum {
|
||||
CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
|
||||
@@ -536,6 +550,21 @@ typedef enum {
|
||||
CURLFTPMETHOD_LAST /* not an option, never use */
|
||||
} curl_ftpmethod;
|
||||
|
||||
/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
|
||||
#define CURLPROTO_HTTP (1<<0)
|
||||
#define CURLPROTO_HTTPS (1<<1)
|
||||
#define CURLPROTO_FTP (1<<2)
|
||||
#define CURLPROTO_FTPS (1<<3)
|
||||
#define CURLPROTO_SCP (1<<4)
|
||||
#define CURLPROTO_SFTP (1<<5)
|
||||
#define CURLPROTO_TELNET (1<<6)
|
||||
#define CURLPROTO_LDAP (1<<7)
|
||||
#define CURLPROTO_LDAPS (1<<8)
|
||||
#define CURLPROTO_DICT (1<<9)
|
||||
#define CURLPROTO_FILE (1<<10)
|
||||
#define CURLPROTO_TFTP (1<<11)
|
||||
#define CURLPROTO_ALL (~0) /* enable everything */
|
||||
|
||||
/* long may be 32 or 64 bits, but we should never depend on anything else
|
||||
but 32 */
|
||||
#define CURLOPTTYPE_LONG 0
|
||||
@@ -868,7 +897,7 @@ typedef enum {
|
||||
/* DNS cache timeout */
|
||||
CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
|
||||
|
||||
/* send linked-list of pre-transfer QUOTE commands (Wesley Laxton)*/
|
||||
/* send linked-list of pre-transfer QUOTE commands */
|
||||
CINIT(PREQUOTE, OBJECTPOINT, 93),
|
||||
|
||||
/* set the debug function */
|
||||
@@ -933,7 +962,10 @@ typedef enum {
|
||||
argument */
|
||||
CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
|
||||
|
||||
/* FTP Option that causes missing dirs to be created on the remote server */
|
||||
/* FTP Option that causes missing dirs to be created on the remote server.
|
||||
In 7.19.4 we introduced the convenience enums for this option using the
|
||||
CURLFTP_CREATE_DIR prefix.
|
||||
*/
|
||||
CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
|
||||
|
||||
/* Set this to a bitmask value to enable the particular authentications
|
||||
@@ -1150,6 +1182,36 @@ typedef enum {
|
||||
CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
|
||||
CINIT(PROXYPASSWORD, OBJECTPOINT, 176),
|
||||
|
||||
/* Comma separated list of hostnames defining no-proxy zones. These should
|
||||
match both hostnames directly, and hostnames within a domain. For
|
||||
example, local.com will match local.com and www.local.com, but NOT
|
||||
notlocal.com or www.notlocal.com. For compatibility with other
|
||||
implementations of this, .local.com will be considered to be the same as
|
||||
local.com. A single * is the only valid wildcard, and effectively
|
||||
disables the use of proxy. */
|
||||
CINIT(NOPROXY, OBJECTPOINT, 177),
|
||||
|
||||
/* block size for TFTP transfers */
|
||||
CINIT(TFTP_BLKSIZE, LONG, 178),
|
||||
|
||||
/* Socks Service */
|
||||
CINIT(SOCKS5_GSSAPI_SERVICE, LONG, 179),
|
||||
|
||||
/* Socks Service */
|
||||
CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
|
||||
|
||||
/* set the bitmask for the protocols that are allowed to be used for the
|
||||
transfer, which thus helps the app which takes URLs from users or other
|
||||
external inputs and want to restrict what protocol(s) to deal
|
||||
with. Defaults to CURLPROTO_ALL. */
|
||||
CINIT(PROTOCOLS, LONG, 181),
|
||||
|
||||
/* set the bitmask for the protocols that libcurl is allowed to follow to,
|
||||
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
|
||||
to be set in both bitmasks to be allowed to get redirected to. Defaults
|
||||
to all protocols except FILE and SCP. */
|
||||
CINIT(REDIR_PROTOCOLS, LONG, 182),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1571,9 +1633,10 @@ typedef enum {
|
||||
CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
|
||||
CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
|
||||
CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
|
||||
CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
|
||||
/* Fill in new entries below here! */
|
||||
|
||||
CURLINFO_LASTONE = 34
|
||||
CURLINFO_LASTONE = 35
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
|
@@ -31,13 +31,13 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.19.3-CVS"
|
||||
#define LIBCURL_VERSION "7.19.4-CVS"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 19
|
||||
#define LIBCURL_VERSION_PATCH 3
|
||||
#define LIBCURL_VERSION_PATCH 4
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
@@ -54,7 +54,7 @@
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x071303
|
||||
#define LIBCURL_VERSION_NUM 0x071304
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -201,6 +201,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
(option) == CURLOPT_PROXYUSERPWD || \
|
||||
(option) == CURLOPT_PROXYUSERNAME || \
|
||||
(option) == CURLOPT_PROXYPASSWORD || \
|
||||
(option) == CURLOPT_NOPROXY || \
|
||||
(option) == CURLOPT_ENCODING || \
|
||||
(option) == CURLOPT_REFERER || \
|
||||
(option) == CURLOPT_USERAGENT || \
|
||||
|
@@ -7,6 +7,6 @@ Makefile
|
||||
config.h
|
||||
stamp-*
|
||||
getdate.c
|
||||
curllib.dsp
|
||||
curllib.vcproj
|
||||
libcurl.dsp
|
||||
libcurl.vcproj
|
||||
*.dist
|
||||
|
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2009, 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
|
||||
@@ -22,16 +22,16 @@
|
||||
###########################################################################
|
||||
AUTOMAKE_OPTIONS = foreign nostdinc
|
||||
|
||||
DSP = curllib.dsp
|
||||
VCPROJ = curllib.vcproj
|
||||
DSP = libcurl.dsp
|
||||
VCPROJ = libcurl.vcproj
|
||||
|
||||
DOCS = README.encoding README.memoryleak README.ares README.curlx \
|
||||
README.hostip README.multi_socket README.httpauth README.pipelining \
|
||||
README.NSS README.curl_off_t
|
||||
|
||||
EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 Makefile.riscos $(DSP) \
|
||||
curllib.dsw config-win32.h config-win32ce.h config-riscos.h config-mac.h \
|
||||
config.h.in makefile.dj config.dos libcurl.framework.make libcurl.plist \
|
||||
libcurl.dsw config-win32.h config-win32ce.h config-riscos.h config-mac.h \
|
||||
config.h.in makefile.dj config.dos libcurl.plist \
|
||||
libcurl.rc config-amigaos.h amigaos.c amigaos.h makefile.amiga \
|
||||
Makefile.netware nwlib.c nwos.c libcurl.imp msvcproj.head msvcproj.foot \
|
||||
config-win32ce.h config-os400.h setup-os400.h config-symbian.h \
|
||||
|
@@ -9,7 +9,8 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.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 gtls.c sslgen.c tftp.c splay.c \
|
||||
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c
|
||||
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \
|
||||
socks_gssapi.c socks_sspi.c curl_sspi.c
|
||||
|
||||
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
||||
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||
@@ -20,4 +21,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
||||
strtoofft.h strerror.h inet_ntop.h curlx.h memory.h setup.h \
|
||||
transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \
|
||||
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
|
||||
curl_base64.h rawstr.h curl_addrinfo.h
|
||||
curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h
|
||||
|
@@ -1,5 +1,25 @@
|
||||
#############################################################
|
||||
# $Id: Makefile.vc6,v 1.19 2004/11/14 13:48:15 giva Exp $
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1999 - 2009, 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: Makefile.am,v 1.139 2008-11-03 08:50:58 bagder Exp $
|
||||
###########################################################################
|
||||
#
|
||||
# Makefile for building libcurl with MSVC6
|
||||
#
|
||||
@@ -430,6 +450,7 @@ X_OBJS= \
|
||||
$(DIROBJ)\content_encoding.obj \
|
||||
$(DIROBJ)\cookie.obj \
|
||||
$(DIROBJ)\curl_addrinfo.obj \
|
||||
$(DIROBJ)\curl_sspi.obj \
|
||||
$(DIROBJ)\dict.obj \
|
||||
$(DIROBJ)\easy.obj \
|
||||
$(DIROBJ)\escape.obj \
|
||||
@@ -469,8 +490,10 @@ X_OBJS= \
|
||||
$(DIROBJ)\sendf.obj \
|
||||
$(DIROBJ)\share.obj \
|
||||
$(DIROBJ)\socks.obj \
|
||||
$(DIROBJ)\socks_sspi.obj \
|
||||
$(DIROBJ)\speedcheck.obj \
|
||||
$(DIROBJ)\splay.obj \
|
||||
$(DIROBJ)\ssh.obj \
|
||||
$(DIROBJ)\sslgen.obj \
|
||||
$(DIROBJ)\ssluse.obj \
|
||||
$(DIROBJ)\strequal.obj \
|
||||
|
@@ -33,42 +33,39 @@ extern int errno, h_errno;
|
||||
#include <stabs.h>
|
||||
void __request(const char *msg);
|
||||
#else
|
||||
# define __request( msg ) Printf( msg "\n\a")
|
||||
# define __request( msg ) Printf( msg "\n\a")
|
||||
#endif
|
||||
|
||||
void amiga_cleanup()
|
||||
{
|
||||
if(SocketBase) {
|
||||
CloseLibrary(SocketBase);
|
||||
SocketBase = NULL;
|
||||
}
|
||||
if(SocketBase) {
|
||||
CloseLibrary(SocketBase);
|
||||
SocketBase = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL amiga_init()
|
||||
{
|
||||
if(!SocketBase)
|
||||
SocketBase = OpenLibrary("bsdsocket.library", 4);
|
||||
if(!SocketBase)
|
||||
SocketBase = OpenLibrary("bsdsocket.library", 4);
|
||||
|
||||
if(!SocketBase) {
|
||||
__request("No TCP/IP Stack running!");
|
||||
return FALSE;
|
||||
}
|
||||
if(!SocketBase) {
|
||||
__request("No TCP/IP Stack running!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(SocketBaseTags(
|
||||
SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
|
||||
// SBTM_SETVAL(SBTC_HERRNOLONGPTR), (ULONG) &h_errno,
|
||||
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
|
||||
TAG_DONE)) {
|
||||
|
||||
__request("SocketBaseTags ERROR");
|
||||
return FALSE;
|
||||
}
|
||||
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
|
||||
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
|
||||
TAG_DONE)) {
|
||||
__request("SocketBaseTags ERROR");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifndef __libnix__
|
||||
atexit(amiga_cleanup);
|
||||
atexit(amiga_cleanup);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef __libnix__
|
||||
|
@@ -403,22 +403,39 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* VS2008 does not support Windows build targets prior to WinXP, */
|
||||
/* so, if no build target has been defined we will target WinXP. */
|
||||
/* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
|
||||
2000 as a supported build target. VS2008 default installations provide an
|
||||
embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
|
||||
valid build target for VS2008. Popular belief is that binaries built using
|
||||
Windows SDK versions 6.X and Windows 2000 as a build target are functional */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define VS2008_MINIMUM_TARGET 0x0500
|
||||
#endif
|
||||
|
||||
/* When no build target is specified VS2008 default build target is Windows
|
||||
Vista, which leaves out even Winsows XP. If no build target has been given
|
||||
for VS2008 we will target the minimum Officially supported build target,
|
||||
which happens to be Windows XP. */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define VS2008_DEFAULT_TARGET 0x0501
|
||||
#endif
|
||||
|
||||
/* VS2008 default target settings and minimum build target check */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# define _WIN32_WINNT VS2008_DEFAULT_TARGET
|
||||
# endif
|
||||
# ifndef WINVER
|
||||
# define WINVER 0x0501
|
||||
# define WINVER VS2008_DEFAULT_TARGET
|
||||
# endif
|
||||
# if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501)
|
||||
# error VS2008 does not support Windows build targets prior to WinXP
|
||||
# if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
|
||||
# error VS2008 does not support Windows build targets prior to Windows 2000
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is quite */
|
||||
/* convoluted, compiler dependant and in some cases even build target dependat. */
|
||||
/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is
|
||||
quite convoluted, compiler dependant and in some cases even build target
|
||||
dependant. */
|
||||
#if defined(HAVE_WS2TCPIP_H)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
|
||||
# define HAVE_FREEADDRINFO 1
|
||||
|
212
lib/connect.c
212
lib/connect.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -54,8 +54,8 @@
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h> /* required for free() prototype, without it, this crashes */
|
||||
#endif /* on macos 68K */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
|
||||
#include <sys/filio.h>
|
||||
@@ -87,6 +87,7 @@
|
||||
#include "multiif.h"
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "inet_ntop.h"
|
||||
#include "inet_pton.h"
|
||||
#include "sslgen.h" /* for Curl_ssl_check_cxn() */
|
||||
|
||||
/* The last #include file should be: */
|
||||
@@ -277,12 +278,15 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
curl_socket_t sockfd, int af)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct sockaddr_in me;
|
||||
|
||||
struct Curl_sockaddr_storage sa;
|
||||
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
|
||||
socklen_t sizeof_sa = 0; /* size of the data sock points to */
|
||||
struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_in6 me6;
|
||||
struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
|
||||
#endif
|
||||
struct sockaddr *sock = NULL; /* bind to this address */
|
||||
socklen_t socksize = 0; /* size of the data sock points to */
|
||||
|
||||
struct Curl_dns_entry *h=NULL;
|
||||
unsigned short port = data->set.localport; /* use this port number, 0 for
|
||||
"random" */
|
||||
@@ -290,40 +294,64 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
int portnum = data->set.localportrange;
|
||||
const char *dev = data->set.str[STRING_DEVICE];
|
||||
int error;
|
||||
char myhost[256] = "";
|
||||
int done = 0; /* -1 for error, 1 for address found */
|
||||
|
||||
/*************************************************************
|
||||
* Select device to bind socket to
|
||||
*************************************************************/
|
||||
if(dev && (strlen(dev)<255) ) {
|
||||
char myhost[256] = "";
|
||||
int rc;
|
||||
bool was_iface = FALSE;
|
||||
if ( !dev && !port )
|
||||
/* no local kind of binding was requested */
|
||||
return CURLE_OK;
|
||||
|
||||
memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
|
||||
|
||||
if(dev && (strlen(dev)<255) ) {
|
||||
|
||||
/* interface */
|
||||
if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) {
|
||||
/*
|
||||
* We now have the numerical IP address in the 'myhost' buffer
|
||||
*/
|
||||
rc = Curl_resolv(conn, myhost, 0, &h);
|
||||
if(rc == CURLRESOLV_PENDING)
|
||||
(void)Curl_wait_for_resolv(conn, &h);
|
||||
infof(data, "Local Interface %s is ip %s using address family %i\n",
|
||||
dev, myhost, af);
|
||||
done = 1;
|
||||
|
||||
if(h) {
|
||||
was_iface = TRUE;
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/* I am not sure any other OSs than Linux that provide this feature, and
|
||||
* at the least I cannot test. --Ben
|
||||
*
|
||||
* This feature allows one to tightly bind the local socket to a
|
||||
* particular interface. This will force even requests to other local
|
||||
* interfaces to go out the external interface.
|
||||
*
|
||||
*
|
||||
* Only bind to the interface when specified as interface, not just as a
|
||||
* hostname or ip address.
|
||||
*/
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
dev, strlen(dev)+1) != 0) {
|
||||
error = SOCKERRNO;
|
||||
infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
|
||||
" will do regular bind\n",
|
||||
dev, error, Curl_strerror(conn, error));
|
||||
/* This is typically "errno 1, error: Operation not permitted" if
|
||||
you're not running as root or another suitable privileged user */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!was_iface) {
|
||||
else {
|
||||
/*
|
||||
* This was not an interface, resolve the name as a host name
|
||||
* or IP number
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Temporarily force name resolution to use only the address type
|
||||
* of the connection. The resolve functions should really be changed
|
||||
* to take a type parameter instead.
|
||||
*/
|
||||
long ipver = data->set.ip_version;
|
||||
int rc;
|
||||
|
||||
if (af == AF_INET)
|
||||
data->set.ip_version = CURL_IPRESOLVE_V4;
|
||||
#ifdef ENABLE_IPV6
|
||||
@@ -338,93 +366,66 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
|
||||
if(h) {
|
||||
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
|
||||
Curl_printable_address(h->addr, myhost, sizeof myhost);
|
||||
Curl_printable_address(h->addr, myhost, sizeof(myhost));
|
||||
infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
|
||||
dev, af, myhost, h->addr->ai_family);
|
||||
Curl_resolv_unlock(data, h);
|
||||
done = 1;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* provided dev was no interface (or interfaces are not supported
|
||||
* e.g. solaris) no ip address and no domain we fail here
|
||||
*/
|
||||
done = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!*myhost || !h) {
|
||||
/* need to fix this
|
||||
h=Curl_gethost(data,
|
||||
getmyhost(*myhost,sizeof(myhost)),
|
||||
hostent_buf,
|
||||
sizeof(hostent_buf));
|
||||
*/
|
||||
if(done > 0) {
|
||||
#ifdef ENABLE_IPV6
|
||||
/* ipv6 address */
|
||||
if((af == AF_INET6) &&
|
||||
(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) {
|
||||
si6->sin6_family = AF_INET6;
|
||||
si6->sin6_port = htons(port);
|
||||
sizeof_sa = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* ipv4 address */
|
||||
if((af == AF_INET) &&
|
||||
(Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
|
||||
si4->sin_family = AF_INET;
|
||||
si4->sin_port = htons(port);
|
||||
sizeof_sa = sizeof(struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
|
||||
if(done < 1) {
|
||||
failf(data, "Couldn't bind to '%s'", dev);
|
||||
if(h)
|
||||
Curl_resolv_unlock(data, h);
|
||||
return CURLE_INTERFACE_FAILED;
|
||||
}
|
||||
|
||||
infof(data, "Bind local address to %s\n", myhost);
|
||||
|
||||
sock = h->addr->ai_addr;
|
||||
socksize = h->addr->ai_addrlen;
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/* I am not sure any other OSs than Linux that provide this feature, and
|
||||
* at the least I cannot test. --Ben
|
||||
*
|
||||
* This feature allows one to tightly bind the local socket to a
|
||||
* particular interface. This will force even requests to other local
|
||||
* interfaces to go out the external interface.
|
||||
*
|
||||
*/
|
||||
if(was_iface) {
|
||||
/* Only bind to the interface when specified as interface, not just as a
|
||||
* hostname or ip address.
|
||||
*/
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
dev, strlen(dev)+1) != 0) {
|
||||
error = SOCKERRNO;
|
||||
infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s; will do regular bind\n",
|
||||
dev, error, Curl_strerror(conn, error));
|
||||
/* This is typically "errno 1, error: Operation not permitted" if
|
||||
you're not running as root or another suitable privileged user */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(port) {
|
||||
/* if a local port number is requested but no local IP, extract the
|
||||
address from the socket */
|
||||
if(af == AF_INET) {
|
||||
memset(&me, 0, sizeof(me));
|
||||
me.sin_family = AF_INET;
|
||||
me.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
sock = (struct sockaddr *)&me;
|
||||
socksize = sizeof(me);
|
||||
|
||||
}
|
||||
else {
|
||||
/* no device was given, prepare sa to match af's needs */
|
||||
#ifdef ENABLE_IPV6
|
||||
else { /* AF_INET6 */
|
||||
memset(&me6, 0, sizeof(me6));
|
||||
me6.sin6_family = AF_INET6;
|
||||
/* in6addr_any isn't always available and since me6 has just been
|
||||
cleared, it's not strictly necessary to use it here */
|
||||
/*me6.sin6_addr = in6addr_any;*/
|
||||
|
||||
sock = (struct sockaddr *)&me6;
|
||||
socksize = sizeof(me6);
|
||||
if ( af == AF_INET6 ) {
|
||||
si6->sin6_family = AF_INET6;
|
||||
si6->sin6_port = htons(port);
|
||||
sizeof_sa = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( af == AF_INET ) {
|
||||
si4->sin_family = AF_INET;
|
||||
si4->sin_port = htons(port);
|
||||
sizeof_sa = sizeof(struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* no local kind of binding was requested */
|
||||
return CURLE_OK;
|
||||
|
||||
do {
|
||||
|
||||
/* Set port number to bind to, 0 makes the system pick one */
|
||||
if(sock->sa_family == AF_INET)
|
||||
me.sin_port = htons(port);
|
||||
#ifdef ENABLE_IPV6
|
||||
else
|
||||
me6.sin6_port = htons(port);
|
||||
#endif
|
||||
|
||||
if( bind(sockfd, sock, socksize) >= 0) {
|
||||
/* we succeeded to bind */
|
||||
if( bind(sockfd, sock, sizeof_sa) >= 0) {
|
||||
/* we succeeded to bind */
|
||||
struct Curl_sockaddr_storage add;
|
||||
socklen_t size = sizeof(add);
|
||||
memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
|
||||
@@ -432,26 +433,23 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
data->state.os_errno = error = SOCKERRNO;
|
||||
failf(data, "getsockname() failed with errno %d: %s",
|
||||
error, Curl_strerror(conn, error));
|
||||
if(h)
|
||||
Curl_resolv_unlock(data, h);
|
||||
return CURLE_INTERFACE_FAILED;
|
||||
}
|
||||
/* We re-use/clobber the port variable here below */
|
||||
if(((struct sockaddr *)&add)->sa_family == AF_INET)
|
||||
port = ntohs(((struct sockaddr_in *)&add)->sin_port);
|
||||
#ifdef ENABLE_IPV6
|
||||
else
|
||||
port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port);
|
||||
#endif
|
||||
infof(data, "Local port: %d\n", port);
|
||||
conn->bits.bound = TRUE;
|
||||
if(h)
|
||||
Curl_resolv_unlock(data, h);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
if(--portnum > 0) {
|
||||
infof(data, "Bind to local port %d failed, trying next\n", port);
|
||||
port++; /* try next port */
|
||||
/* We re-use/clobber the port variable here below */
|
||||
if(sock->sa_family == AF_INET)
|
||||
si4->sin_port = ntohs(port);
|
||||
#ifdef ENABLE_IPV6
|
||||
else
|
||||
si6->sin6_port = ntohs(port);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
break;
|
||||
@@ -460,8 +458,6 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
data->state.os_errno = error = SOCKERRNO;
|
||||
failf(data, "bind failed with errno %d: %s",
|
||||
error, Curl_strerror(conn, error));
|
||||
if(h)
|
||||
Curl_resolv_unlock(data, h);
|
||||
|
||||
return CURLE_INTERFACE_FAILED;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -133,9 +133,10 @@ inflate_stream(struct connectdata *conn,
|
||||
/* some servers seem to not generate zlib headers, so this is an attempt
|
||||
to fix and continue anyway */
|
||||
|
||||
(void) inflateEnd(z); /* don't care about the return code */
|
||||
(void) inflateEnd(z); /* don't care about the return code */
|
||||
if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
|
||||
return process_zlib_error(conn, z);
|
||||
free(decomp);
|
||||
return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
|
||||
}
|
||||
z->next_in = orig_in;
|
||||
z->avail_in = nread;
|
||||
|
@@ -91,7 +91,7 @@ struct Cookie *Curl_cookie_add(struct SessionHandle *data,
|
||||
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
|
||||
const char *, struct CookieInfo *, bool);
|
||||
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
|
||||
const char *, bool);
|
||||
const char *, bool);
|
||||
void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo);
|
||||
void Curl_cookie_clearall(struct CookieInfo *cookies);
|
||||
void Curl_cookie_clearsess(struct CookieInfo *cookies);
|
||||
|
119
lib/curl_sspi.c
Normal file
119
lib/curl_sspi.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, 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$
|
||||
***************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_sspi.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#include "memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
/* Handle of security.dll or secur32.dll, depending on Windows version */
|
||||
HMODULE s_hSecDll = NULL;
|
||||
|
||||
/* Pointer to SSPI dispatch table */
|
||||
PSecurityFunctionTableA s_pSecFn = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Curl_sspi_global_init()
|
||||
*
|
||||
* This is used to load the Security Service Provider Interface (SSPI)
|
||||
* dynamic link library portably across all Windows versions, without
|
||||
* the need to directly link libcurl, nor the application using it, at
|
||||
* build time.
|
||||
*
|
||||
* Once this function has been executed, Windows SSPI functions can be
|
||||
* called through the Security Service Provider Interface dispatch table.
|
||||
*/
|
||||
|
||||
CURLcode
|
||||
Curl_sspi_global_init(void)
|
||||
{
|
||||
OSVERSIONINFO osver;
|
||||
INIT_SECURITY_INTERFACE_A pInitSecurityInterface;
|
||||
|
||||
/* If security interface is not yet initialized try to do this */
|
||||
if(s_hSecDll == NULL) {
|
||||
|
||||
/* Find out Windows version */
|
||||
memset(&osver, 0, sizeof(osver));
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
if(! GetVersionEx(&osver))
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* Security Service Provider Interface (SSPI) functions are located in
|
||||
* security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
|
||||
* have both these DLLs (security.dll forwards calls to secur32.dll) */
|
||||
|
||||
/* Load SSPI dll into the address space of the calling process */
|
||||
if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT
|
||||
&& osver.dwMajorVersion == 4)
|
||||
s_hSecDll = LoadLibrary("security.dll");
|
||||
else
|
||||
s_hSecDll = LoadLibrary("secur32.dll");
|
||||
if(! s_hSecDll)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
|
||||
pInitSecurityInterface = (INIT_SECURITY_INTERFACE_A)
|
||||
GetProcAddress(s_hSecDll, "InitSecurityInterfaceA");
|
||||
if(! pInitSecurityInterface)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* Get pointer to Security Service Provider Interface dispatch table */
|
||||
s_pSecFn = pInitSecurityInterface();
|
||||
if(! s_pSecFn)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Curl_sspi_global_cleanup()
|
||||
*
|
||||
* This deinitializes the Security Service Provider Interface from libcurl.
|
||||
*/
|
||||
|
||||
void
|
||||
Curl_sspi_global_cleanup(void)
|
||||
{
|
||||
if(s_hSecDll) {
|
||||
FreeLibrary(s_hSecDll);
|
||||
s_hSecDll = NULL;
|
||||
s_pSecFn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI */
|
74
lib/curl_sspi.h
Normal file
74
lib/curl_sspi.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef HEADER_CURL_SSPI_H
|
||||
#define HEADER_CURL_SSPI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, 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$
|
||||
***************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
/*
|
||||
* When including the folowing three headers, it is mandatory to define either
|
||||
* SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code.
|
||||
*/
|
||||
|
||||
#undef SECURITY_WIN32
|
||||
#undef SECURITY_KERNEL
|
||||
#define SECURITY_WIN32 1
|
||||
#include <security.h>
|
||||
#include <sspi.h>
|
||||
#include <rpc.h>
|
||||
|
||||
/* Provide some definitions missing in MinGW's headers */
|
||||
|
||||
#ifndef SEC_I_CONTEXT_EXPIRED
|
||||
# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L)
|
||||
#endif
|
||||
#ifndef SEC_E_BUFFER_TOO_SMALL
|
||||
# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L)
|
||||
#endif
|
||||
#ifndef SEC_E_CONTEXT_EXPIRED
|
||||
# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L)
|
||||
#endif
|
||||
#ifndef SEC_E_CRYPTO_SYSTEM_INVALID
|
||||
# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L)
|
||||
#endif
|
||||
#ifndef SEC_E_MESSAGE_ALTERED
|
||||
# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL)
|
||||
#endif
|
||||
#ifndef SEC_E_OUT_OF_SEQUENCE
|
||||
# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L)
|
||||
#endif
|
||||
|
||||
CURLcode Curl_sspi_global_init(void);
|
||||
void Curl_sspi_global_cleanup(void);
|
||||
|
||||
/* Forward-declaration of global variables defined in curl_sspi.c */
|
||||
|
||||
extern HMODULE s_hSecDll;
|
||||
extern PSecurityFunctionTableA s_pSecFn;
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI */
|
||||
#endif /* HEADER_CURL_SSPI_H */
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -111,7 +111,7 @@ static void win32_cleanup(void)
|
||||
WSACleanup();
|
||||
#endif
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
Curl_ntlm_global_cleanup();
|
||||
Curl_sspi_global_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ static CURLcode win32_init(void)
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
{
|
||||
CURLcode err = Curl_ntlm_global_init();
|
||||
CURLcode err = Curl_sspi_global_init();
|
||||
if (err != CURLE_OK)
|
||||
return err;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -496,6 +496,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
|
||||
tm->tm_sec);
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
|
||||
}
|
||||
/* if we fstat()ed the file, set the file size to make it available post-
|
||||
transfer */
|
||||
if(fstated)
|
||||
Curl_pgrsSetDownloadSize(data, expected_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
44
lib/ftp.c
44
lib/ftp.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -89,6 +89,7 @@
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "multiif.h"
|
||||
#include "url.h"
|
||||
#include "rawstr.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -362,6 +363,7 @@ static void ftp_respinit(struct connectdata *conn)
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
ftpc->nread_resp = 0;
|
||||
ftpc->linestart_resp = conn->data->state.buffer;
|
||||
ftpc->pending_resp = TRUE;
|
||||
}
|
||||
|
||||
/* macro to check for a three-digit ftp status code at the start of the
|
||||
@@ -589,6 +591,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
/* store the latest code for later retrieval */
|
||||
conn->data->info.httpcode=code;
|
||||
|
||||
ftpc->pending_resp = FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -714,6 +718,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
||||
|
||||
} /* while there's buffer left and loop is requested */
|
||||
|
||||
ftpc->pending_resp = FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -814,7 +820,7 @@ static int ftp_getsock(struct connectdata *conn,
|
||||
|
||||
/* This is called after the FTP_QUOTE state is passed.
|
||||
|
||||
ftp_state_cwd() sends the range of PWD commands to the server to change to
|
||||
ftp_state_cwd() sends the range of CWD commands to the server to change to
|
||||
the correct directory. It may also need to send MKD commands to create
|
||||
missing ones, if that option is enabled.
|
||||
*/
|
||||
@@ -827,7 +833,13 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
|
||||
/* already done and fine */
|
||||
result = ftp_state_post_cwd(conn);
|
||||
else {
|
||||
ftpc->count2 = 0;
|
||||
ftpc->count2 = 0; /* count2 counts failed CWDs */
|
||||
|
||||
/* count3 is set to allow a MKD to fail once. In the case when first CWD
|
||||
fails and then MKD fails (due to another session raced it to create the
|
||||
dir) this then allows for a second try to CWD to it */
|
||||
ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0;
|
||||
|
||||
if(conn->bits.reuse && ftpc->entrypath) {
|
||||
/* This is a re-used connection. Since we change directory to where the
|
||||
transfer is taking place, we must first get back to the original dir
|
||||
@@ -1893,6 +1905,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
break;
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
case CURLPROXY_HTTP:
|
||||
case CURLPROXY_HTTP_1_0:
|
||||
/* do nothing here. handled later. */
|
||||
break;
|
||||
default:
|
||||
@@ -1900,7 +1913,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
break;
|
||||
}
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
|
||||
/* FIX: this MUST wait for a proper connect first if 'connected' is
|
||||
* FALSE */
|
||||
@@ -1926,7 +1939,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
|
||||
|
||||
state(conn, FTP_STOP); /* this phase is completed */
|
||||
|
||||
@@ -2043,6 +2056,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
if(data->info.filetime <= data->set.timevalue) {
|
||||
infof(data, "The requested document is not new enough\n");
|
||||
ftp->transfer = FTPTRANSFER_NONE; /* mark this to not transfer data */
|
||||
data->info.timecond = TRUE;
|
||||
state(conn, FTP_STOP);
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -2051,6 +2065,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
if(data->info.filetime > data->set.timevalue) {
|
||||
infof(data, "The requested document is not old enough\n");
|
||||
ftp->transfer = FTPTRANSFER_NONE; /* mark this to not transfer data */
|
||||
data->info.timecond = TRUE;
|
||||
state(conn, FTP_STOP);
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -2295,6 +2310,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
|
||||
SECONDARYSOCKET, ftp->bytecountp);
|
||||
state(conn, FTP_STOP);
|
||||
|
||||
conn->proto.ftpc.pending_resp = TRUE; /* we expect a server response more */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2407,6 +2424,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
conn->proto.ftpc.pending_resp = TRUE; /* we expect a server response more */
|
||||
state(conn, FTP_STOP);
|
||||
}
|
||||
else {
|
||||
@@ -2417,7 +2435,8 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
failf(data, "RETR response: %03d", ftpcode);
|
||||
return CURLE_FTP_COULDNT_RETR_FILE;
|
||||
return instate == FTP_RETR && ftpcode == 550? CURLE_REMOTE_FILE_NOT_FOUND:
|
||||
CURLE_FTP_COULDNT_RETR_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2830,7 +2849,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
||||
break;
|
||||
|
||||
case FTP_MKD:
|
||||
if(ftpcode/100 != 2) {
|
||||
if((ftpcode/100 != 2) && !ftpc->count3--) {
|
||||
/* failure to MKD the dir */
|
||||
failf(data, "Failed to MKD dir: %03d", ftpcode);
|
||||
return CURLE_REMOTE_ACCESS_DENIED;
|
||||
@@ -3059,7 +3078,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
||||
|
||||
ftpc->response_time = RESP_TIMEOUT; /* set default response time-out */
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
|
||||
/* BLOCKING */
|
||||
/* We want "seamless" FTP operations through HTTP proxy tunnel */
|
||||
@@ -3082,7 +3101,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
|
||||
if(CURLE_OK != result)
|
||||
return result;
|
||||
}
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
|
||||
|
||||
if(conn->protocol & PROT_FTPS) {
|
||||
/* BLOCKING */
|
||||
@@ -3149,6 +3168,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
case CURLE_UPLOAD_FAILED:
|
||||
case CURLE_REMOTE_ACCESS_DENIED:
|
||||
case CURLE_FILESIZE_EXCEEDED:
|
||||
case CURLE_REMOTE_FILE_NOT_FOUND:
|
||||
case CURLE_WRITE_ERROR:
|
||||
/* the connection stays alive fine even though this happened */
|
||||
/* fall-through */
|
||||
case CURLE_OK: /* doesn't affect the control connection's status */
|
||||
@@ -3227,7 +3248,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if((ftp->transfer == FTPTRANSFER_BODY) && !status && !premature) {
|
||||
if((ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
|
||||
ftpc->pending_resp && !premature) {
|
||||
/*
|
||||
* Let's see what the server says about the transfer we just performed,
|
||||
* but lower the timeout as sometimes this connection has died while the
|
||||
@@ -4141,7 +4163,7 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
|
||||
|
||||
if(type) {
|
||||
*type = 0; /* it was in the middle of the hostname */
|
||||
command = (char) toupper((int) type[6]);
|
||||
command = Curl_raw_toupper(type[6]);
|
||||
|
||||
switch (command) {
|
||||
case 'A': /* ASCII mode */
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "memory.h"
|
||||
#include "sslgen.h"
|
||||
#include "connect.h" /* Curl_getconnectinfo() */
|
||||
#include "progress.h"
|
||||
|
||||
/* Make this the last #include */
|
||||
#include "memdebug.h"
|
||||
@@ -167,10 +168,12 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
||||
*param_longp = data->set.ssl.certverifyresult;
|
||||
break;
|
||||
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
|
||||
*param_doublep = (double)data->progress.size_dl;
|
||||
*param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
|
||||
(double)data->progress.size_dl:-1;
|
||||
break;
|
||||
case CURLINFO_CONTENT_LENGTH_UPLOAD:
|
||||
*param_doublep = (double)data->progress.size_ul;
|
||||
*param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
|
||||
(double)data->progress.size_ul:-1;
|
||||
break;
|
||||
case CURLINFO_REDIRECT_TIME:
|
||||
*param_doublep = data->progress.t_redirect;
|
||||
@@ -228,6 +231,10 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
||||
ptr.to_certinfo = &data->info.certs;
|
||||
*param_slistp = ptr.to_slist;
|
||||
break;
|
||||
case CURLINFO_CONDITION_UNMET:
|
||||
/* return if the condition prevented the document to get transfered */
|
||||
*param_longp = data->info.timecond;
|
||||
break;
|
||||
default:
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
|
60
lib/gtls.c
60
lib/gtls.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -33,6 +33,7 @@
|
||||
#ifdef USE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/x509.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -85,19 +86,14 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
|
||||
return sread(s, buf, len);
|
||||
}
|
||||
|
||||
/* Global GnuTLS init, called from Curl_ssl_init() */
|
||||
int Curl_gtls_init(void)
|
||||
{
|
||||
/* Unfortunately we can not init here, things like curl --version will
|
||||
* fail to work if there is no egd socket available because libgcrypt
|
||||
* will EXIT the application!!
|
||||
* By doing the actual init later (before actually trying to use GnuTLS),
|
||||
* we can at least provide basic info etc.
|
||||
/* Curl_gtls_init()
|
||||
*
|
||||
* Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
|
||||
* are not thread-safe and thus this function itself is not thread-safe and
|
||||
* must only be called from within curl_global_init() to keep the thread
|
||||
* situation under control!
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _Curl_gtls_init(void)
|
||||
int Curl_gtls_init(void)
|
||||
{
|
||||
int ret = 1;
|
||||
if(!gtls_inited) {
|
||||
@@ -180,7 +176,7 @@ static CURLcode handshake(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
int rc;
|
||||
if(!gtls_inited)
|
||||
_Curl_gtls_init();
|
||||
Curl_gtls_init();
|
||||
do {
|
||||
rc = gnutls_handshake(session);
|
||||
|
||||
@@ -271,7 +267,7 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
|
||||
if(!gtls_inited)
|
||||
_Curl_gtls_init();
|
||||
Curl_gtls_init();
|
||||
|
||||
/* GnuTLS only supports SSLv3 and TLSv1 */
|
||||
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
|
||||
@@ -308,8 +304,8 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
if(data->set.ssl.CRLfile) {
|
||||
/* set the CRL list file */
|
||||
rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
|
||||
data->set.ssl.CRLfile,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
data->set.ssl.CRLfile,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
if(rc < 0) {
|
||||
failf(data, "error reading crl file %s (%s)\n",
|
||||
data->set.ssl.CRLfile, gnutls_strerror(rc));
|
||||
@@ -436,8 +432,8 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
if(verify_status & GNUTLS_CERT_INVALID) {
|
||||
if(data->set.ssl.verifypeer) {
|
||||
failf(data, "server certificate verification failed. CAfile: %s "
|
||||
"CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
|
||||
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
|
||||
"CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
|
||||
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
|
||||
return CURLE_SSL_CACERT;
|
||||
}
|
||||
else
|
||||
@@ -464,11 +460,11 @@ Curl_gtls_connect(struct connectdata *conn,
|
||||
unload_file(issuerp);
|
||||
if (rc <= 0) {
|
||||
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
|
||||
data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
|
||||
data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
|
||||
return CURLE_SSL_ISSUER_ERROR;
|
||||
}
|
||||
infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
|
||||
data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
|
||||
data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
|
||||
}
|
||||
|
||||
size=sizeof(certbuf);
|
||||
@@ -777,4 +773,26 @@ size_t Curl_gtls_version(char *buffer, size_t size)
|
||||
return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
|
||||
}
|
||||
|
||||
int Curl_gtls_seed(struct SessionHandle *data)
|
||||
{
|
||||
/* we have the "SSL is seeded" boolean static to prevent multiple
|
||||
time-consuming seedings in vain */
|
||||
static bool ssl_seeded = FALSE;
|
||||
|
||||
/* Quickly add a bit of entropy */
|
||||
gcry_fast_random_poll();
|
||||
|
||||
if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
|
||||
data->set.str[STRING_SSL_EGDSOCKET]) {
|
||||
|
||||
/* TODO: to a good job seeding the RNG
|
||||
This may involve the gcry_control function and these options:
|
||||
GCRYCTL_SET_RANDOM_SEED_FILE
|
||||
GCRYCTL_SET_RNDEGD_SOCKET
|
||||
*/
|
||||
ssl_seeded = TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* USE_GNUTLS */
|
||||
|
@@ -47,6 +47,7 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
|
||||
void Curl_gtls_session_free(void *ptr);
|
||||
size_t Curl_gtls_version(char *buffer, size_t size);
|
||||
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
|
||||
int Curl_gtls_seed(struct SessionHandle *data);
|
||||
|
||||
/* API setup for GnuTLS */
|
||||
#define curlssl_init Curl_gtls_init
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -326,11 +326,14 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||
}
|
||||
|
||||
switch(data->set.ip_version) {
|
||||
default:
|
||||
#if ARES_VERSION >= 0x010601
|
||||
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
|
||||
c-ares versions this just falls through and defaults
|
||||
to PF_INET */
|
||||
break;
|
||||
#endif
|
||||
case CURL_IPRESOLVE_V4:
|
||||
default: /* By default we try ipv4, as PF_UNSPEC isn't supported by c-ares.
|
||||
This is a bit disturbing since users may very well assume that
|
||||
both kinds of addresses are asked for, but the problem is really
|
||||
in c-ares' end here. */
|
||||
family = PF_INET;
|
||||
break;
|
||||
case CURL_IPRESOLVE_V6:
|
||||
|
19
lib/http.c
19
lib/http.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -516,6 +516,10 @@ output_auth_headers(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
const char *auth=NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
#ifdef HAVE_GSSAPI
|
||||
struct negotiatedata *negdata = proxy?
|
||||
&data->state.proxyneg:&data->state.negotiate;
|
||||
#endif
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
(void)request;
|
||||
@@ -524,14 +528,13 @@ output_auth_headers(struct connectdata *conn,
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
|
||||
data->state.negotiate.context &&
|
||||
!GSS_ERROR(data->state.negotiate.status)) {
|
||||
negdata->context && !GSS_ERROR(negdata->status)) {
|
||||
auth="GSS-Negotiate";
|
||||
result = Curl_output_negotiate(conn, proxy);
|
||||
if(result)
|
||||
return result;
|
||||
authstatus->done = TRUE;
|
||||
data->state.negotiate.state = GSS_AUTHSENT;
|
||||
negdata->state = GSS_AUTHSENT;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -1343,6 +1346,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
char *host=(char *)"";
|
||||
const char *proxyconn="";
|
||||
const char *useragent="";
|
||||
const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
|
||||
"1.0" : "1.1";
|
||||
|
||||
if(!checkheaders(data, "Host:")) {
|
||||
host = aprintf("Host: %s\r\n", host_port);
|
||||
@@ -1363,12 +1368,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
/* BLOCKING */
|
||||
result =
|
||||
add_bufferf(req_buffer,
|
||||
"CONNECT %s:%d HTTP/1.0\r\n"
|
||||
"CONNECT %s:%d HTTP/%s\r\n"
|
||||
"%s" /* Host: */
|
||||
"%s" /* Proxy-Authorization */
|
||||
"%s" /* User-Agent */
|
||||
"%s", /* Proxy-Connection */
|
||||
hostname, remote_port,
|
||||
hostname, remote_port, http,
|
||||
host,
|
||||
conn->allocptr.proxyuserpwd?
|
||||
conn->allocptr.proxyuserpwd:"",
|
||||
@@ -2271,7 +2276,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
|
||||
char *p = strstr(ppath, ";type=");
|
||||
if(p && p[6] && p[7] == 0) {
|
||||
switch (toupper((int)((unsigned char)p[6]))) {
|
||||
switch (Curl_raw_toupper(p[6])) {
|
||||
case 'A':
|
||||
case 'D':
|
||||
case 'I':
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -47,6 +47,77 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#define MAX_VALUE_LENGTH 256
|
||||
#define MAX_CONTENT_LENGTH 1024
|
||||
|
||||
/*
|
||||
* Return 0 on success and then the buffers are filled in fine.
|
||||
*
|
||||
* Non-zero means failure to parse.
|
||||
*/
|
||||
static int get_pair(const char *str, char *value, char *content,
|
||||
const char **endptr)
|
||||
{
|
||||
int c;
|
||||
bool starts_with_quote = FALSE;
|
||||
bool escape = FALSE;
|
||||
|
||||
for(c=MAX_VALUE_LENGTH-1; (*str && (*str != '=') && c--); )
|
||||
*value++ = *str++;
|
||||
*value=0;
|
||||
|
||||
if('=' != *str++)
|
||||
/* eek, no match */
|
||||
return 1;
|
||||
|
||||
if('\"' == *str) {
|
||||
/* this starts with a quote so it must end with one as well! */
|
||||
str++;
|
||||
starts_with_quote = TRUE;
|
||||
}
|
||||
|
||||
for(c=MAX_CONTENT_LENGTH-1; *str && c--; str++) {
|
||||
switch(*str) {
|
||||
case '\\':
|
||||
if(!escape) {
|
||||
/* possibly the start of an escaped quote */
|
||||
escape = TRUE;
|
||||
*content++ = '\\'; /* even though this is an escape character, we still
|
||||
store it as-is in the target buffer */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
if(!starts_with_quote) {
|
||||
/* this signals the end of the content if we didn't get a starting quote
|
||||
and then we do "sloppy" parsing */
|
||||
c=0; /* the end */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
/* end of string */
|
||||
c=0;
|
||||
continue;
|
||||
case '\"':
|
||||
if(!escape && starts_with_quote) {
|
||||
/* end of string */
|
||||
c=0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
escape = FALSE;
|
||||
*content++ = *str;
|
||||
}
|
||||
*content=0;
|
||||
|
||||
*endptr = str;
|
||||
|
||||
return 0; /* all is fine! */
|
||||
}
|
||||
|
||||
/* Test example headers:
|
||||
|
||||
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
|
||||
@@ -90,26 +161,16 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
||||
Curl_digest_cleanup_one(d);
|
||||
|
||||
while(more) {
|
||||
char value[256];
|
||||
char content[1024];
|
||||
char value[MAX_VALUE_LENGTH];
|
||||
char content[MAX_CONTENT_LENGTH];
|
||||
size_t totlen=0;
|
||||
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
/* how big can these strings be? */
|
||||
if((2 == sscanf(header, "%255[^=]=\"%1023[^\"]\"",
|
||||
value, content)) ||
|
||||
/* try the same scan but without quotes around the content but don't
|
||||
include the possibly trailing comma, newline or carriage return */
|
||||
(2 == sscanf(header, "%255[^=]=%1023[^\r\n,]",
|
||||
value, content)) ) {
|
||||
if(!strcmp("\"\"", content)) {
|
||||
/* for the name="" case where we get only the "" in the content
|
||||
* variable, simply clear the content then
|
||||
*/
|
||||
content[0]=0;
|
||||
}
|
||||
/* extract a value=content pair */
|
||||
if(!get_pair(header, value, content, &header)) {
|
||||
|
||||
if(Curl_raw_equal(value, "nonce")) {
|
||||
d->nonce = strdup(content);
|
||||
if(!d->nonce)
|
||||
@@ -185,7 +246,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
||||
else
|
||||
break; /* we're done here */
|
||||
|
||||
header += totlen;
|
||||
/* pass all additional spaces here */
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
@@ -368,7 +428,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
Further details on Digest implementation differences:
|
||||
http://www.fngtps.com/2006/09/http-authentication
|
||||
*/
|
||||
if(authp->iestyle && (tmp = strchr((char *)uripath, '?'))) {
|
||||
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
|
||||
md5this = (unsigned char *)aprintf("%s:%.*s", request,
|
||||
(int)(tmp - (char *)uripath), uripath);
|
||||
}
|
||||
|
184
lib/http_ntlm.c
184
lib/http_ntlm.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -60,7 +60,6 @@
|
||||
#include "http_ntlm.h"
|
||||
#include "url.h"
|
||||
#include "memory.h"
|
||||
#include "ssluse.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -68,9 +67,8 @@
|
||||
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
|
||||
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
|
||||
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
|
||||
# ifdef USE_SSLEAY
|
||||
#ifdef USE_SSLEAY
|
||||
#include "ssluse.h"
|
||||
# ifdef USE_OPENSSL
|
||||
# include <openssl/des.h>
|
||||
# include <openssl/md4.h>
|
||||
@@ -84,9 +82,6 @@
|
||||
# include <ssl.h>
|
||||
# include <rand.h>
|
||||
# endif
|
||||
# else
|
||||
# error "Can't compile NTLM support without OpenSSL."
|
||||
# endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00907001L
|
||||
#define DES_key_schedule des_key_schedule
|
||||
@@ -104,15 +99,20 @@
|
||||
#define DESKEY(x) &x
|
||||
#endif
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
#include "gtls.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
|
||||
#elif defined(USE_WINDOWS_SSPI)
|
||||
|
||||
#include "curl_sspi.h"
|
||||
|
||||
#else
|
||||
|
||||
#include <rpc.h>
|
||||
|
||||
/* Handle of security.dll or secur32.dll, depending on Windows version */
|
||||
static HMODULE s_hSecDll = NULL;
|
||||
/* Pointer to SSPI dispatch table */
|
||||
static PSecurityFunctionTable s_pSecFn = NULL;
|
||||
|
||||
# error "Can't compile NTLM support without a crypto library."
|
||||
#endif
|
||||
|
||||
/* The last #include file should be: */
|
||||
@@ -319,11 +319,12 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
|
||||
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
/*
|
||||
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
|
||||
* key schedule ks is also set.
|
||||
*/
|
||||
static void setup_des_key(unsigned char *key_56,
|
||||
static void setup_des_key(const unsigned char *key_56,
|
||||
DES_key_schedule DESKEYARG(ks))
|
||||
{
|
||||
DES_cblock key;
|
||||
@@ -340,16 +341,39 @@ static void setup_des_key(unsigned char *key_56,
|
||||
DES_set_odd_parity(&key);
|
||||
DES_set_key(&key, ks);
|
||||
}
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
/*
|
||||
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
|
||||
*/
|
||||
static void setup_des_key(const unsigned char *key_56,
|
||||
gcry_cipher_hd_t *des)
|
||||
{
|
||||
char key[8];
|
||||
|
||||
key[0] = key_56[0];
|
||||
key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
|
||||
key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
|
||||
key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
|
||||
key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
|
||||
key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
|
||||
key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
|
||||
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
|
||||
|
||||
gcry_cipher_setkey(*des, key, 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
|
||||
* 8 byte plaintext is encrypted with each key and the resulting 24
|
||||
* bytes are stored in the results array.
|
||||
*/
|
||||
static void lm_resp(unsigned char *keys,
|
||||
unsigned char *plaintext,
|
||||
unsigned char *results)
|
||||
static void lm_resp(const unsigned char *keys,
|
||||
const unsigned char *plaintext,
|
||||
unsigned char *results)
|
||||
{
|
||||
#ifdef USE_SSLEAY
|
||||
DES_key_schedule ks;
|
||||
|
||||
setup_des_key(keys, DESKEY(ks));
|
||||
@@ -363,6 +387,24 @@ static void lm_resp(unsigned char *keys,
|
||||
setup_des_key(keys+14, DESKEY(ks));
|
||||
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
|
||||
DESKEY(ks), DES_ENCRYPT);
|
||||
#elif USE_GNUTLS
|
||||
gcry_cipher_hd_t des;
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(keys, &des);
|
||||
gcry_cipher_encrypt(des, results, 8, plaintext, 8);
|
||||
gcry_cipher_close(des);
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(keys+7, &des);
|
||||
gcry_cipher_encrypt(des, results+8, 8, plaintext, 8);
|
||||
gcry_cipher_close(des);
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(keys+14, &des);
|
||||
gcry_cipher_encrypt(des, results+16, 8, plaintext, 8);
|
||||
gcry_cipher_close(des);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -377,17 +419,10 @@ static void mk_lm_hash(struct SessionHandle *data,
|
||||
static const unsigned char magic[] = {
|
||||
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
|
||||
};
|
||||
unsigned int i;
|
||||
size_t len = strlen(password);
|
||||
size_t len = CURLMIN(strlen(password), 14);
|
||||
|
||||
if(len > 14)
|
||||
len = 14;
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
pw[i] = (unsigned char)toupper(password[i]);
|
||||
|
||||
for (; i<14; i++)
|
||||
pw[i] = 0;
|
||||
Curl_strntoupper((char *)pw, password, len);
|
||||
memset(&pw[len], 0, 14-len);
|
||||
|
||||
#ifdef CURL_DOES_CONVERSIONS
|
||||
/*
|
||||
@@ -403,6 +438,7 @@ static void mk_lm_hash(struct SessionHandle *data,
|
||||
{
|
||||
/* Create LanManager hashed password. */
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
DES_key_schedule ks;
|
||||
|
||||
setup_des_key(pw, DESKEY(ks));
|
||||
@@ -412,6 +448,19 @@ static void mk_lm_hash(struct SessionHandle *data,
|
||||
setup_des_key(pw+7, DESKEY(ks));
|
||||
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
|
||||
DESKEY(ks), DES_ENCRYPT);
|
||||
#elif USE_GNUTLS
|
||||
gcry_cipher_hd_t des;
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(pw, &des);
|
||||
gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
|
||||
gcry_cipher_close(des);
|
||||
|
||||
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
||||
setup_des_key(pw+7, &des);
|
||||
gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8);
|
||||
gcry_cipher_close(des);
|
||||
#endif
|
||||
|
||||
memset(lmbuffer + 16, 0, 21 - 16);
|
||||
}
|
||||
@@ -455,11 +504,18 @@ static CURLcode mk_nt_hash(struct SessionHandle *data,
|
||||
|
||||
{
|
||||
/* Create NT hashed password. */
|
||||
#ifdef USE_SSLEAY
|
||||
MD4_CTX MD4pw;
|
||||
|
||||
MD4_Init(&MD4pw);
|
||||
MD4_Update(&MD4pw, pw, 2*len);
|
||||
MD4_Final(ntbuffer, &MD4pw);
|
||||
#elif USE_GNUTLS
|
||||
gcry_md_hd_t MD4pw;
|
||||
gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
|
||||
gcry_md_write(MD4pw, pw, 2*len);
|
||||
memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
|
||||
gcry_md_close(MD4pw);
|
||||
#endif
|
||||
|
||||
memset(ntbuffer + 16, 0, 21 - 16);
|
||||
}
|
||||
@@ -559,7 +615,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
if (s_hSecDll == NULL) {
|
||||
/* not thread safe and leaks - use curl_global_init() to avoid */
|
||||
CURLcode err = Curl_ntlm_global_init();
|
||||
CURLcode err = Curl_sspi_global_init();
|
||||
if (s_hSecDll == NULL)
|
||||
return err;
|
||||
}
|
||||
@@ -618,7 +674,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
ntlm->p_identity = NULL;
|
||||
}
|
||||
|
||||
if(s_pSecFn->AcquireCredentialsHandle(
|
||||
if(s_pSecFn->AcquireCredentialsHandleA(
|
||||
NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
|
||||
NULL, NULL, &ntlm->handle, &tsDummy
|
||||
) != SEC_E_OK) {
|
||||
@@ -632,7 +688,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
buf.BufferType = SECBUFFER_TOKEN;
|
||||
buf.pvBuffer = ntlmbuf;
|
||||
|
||||
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL,
|
||||
status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
|
||||
(char *) host,
|
||||
ISC_REQ_CONFIDENTIALITY |
|
||||
ISC_REQ_REPLAY_DETECT |
|
||||
@@ -788,7 +844,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
type_3.pvBuffer = ntlmbuf;
|
||||
type_3.cbBuffer = sizeof(ntlmbuf);
|
||||
|
||||
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, &ntlm->c_handle,
|
||||
status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, &ntlm->c_handle,
|
||||
(char *) host,
|
||||
ISC_REQ_CONFIDENTIALITY |
|
||||
ISC_REQ_REPLAY_DETECT |
|
||||
@@ -849,12 +905,18 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
unsigned char ntbuffer[0x18];
|
||||
unsigned char tmp[0x18];
|
||||
unsigned char md5sum[MD5_DIGEST_LENGTH];
|
||||
MD5_CTX MD5pw;
|
||||
unsigned char entropy[8];
|
||||
|
||||
/* Need to create 8 bytes random data */
|
||||
#ifdef USE_SSLEAY
|
||||
MD5_CTX MD5pw;
|
||||
Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
|
||||
RAND_bytes(entropy,8);
|
||||
#elif USE_GNUTLS
|
||||
gcry_md_hd_t MD5pw;
|
||||
Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
|
||||
gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
|
||||
#endif
|
||||
|
||||
/* 8 bytes random data as challenge in lmresp */
|
||||
memcpy(lmresp,entropy,8);
|
||||
@@ -865,9 +927,17 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
||||
memcpy(tmp,&ntlm->nonce[0],8);
|
||||
memcpy(tmp+8,entropy,8);
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
MD5_Init(&MD5pw);
|
||||
MD5_Update(&MD5pw, tmp, 16);
|
||||
MD5_Final(md5sum, &MD5pw);
|
||||
#elif USE_GNUTLS
|
||||
gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
|
||||
gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
|
||||
memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
|
||||
gcry_md_close(MD5pw);
|
||||
#endif
|
||||
|
||||
/* We shall only use the first 8 bytes of md5sum,
|
||||
but the des code in lm_resp only encrypt the first 8 bytes */
|
||||
if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
|
||||
@@ -1110,48 +1180,6 @@ Curl_ntlm_cleanup(struct connectdata *conn)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
CURLcode Curl_ntlm_global_init(void)
|
||||
{
|
||||
/* If security interface is not yet initialized try to do this */
|
||||
if(s_hSecDll == NULL) {
|
||||
/* Determine Windows version. Security functions are located in
|
||||
* security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
|
||||
* contain both these DLLs (security.dll just forwards calls to
|
||||
* secur32.dll)
|
||||
*/
|
||||
OSVERSIONINFO osver;
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
GetVersionEx(&osver);
|
||||
if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT
|
||||
&& osver.dwMajorVersion == 4)
|
||||
s_hSecDll = LoadLibrary("security.dll");
|
||||
else
|
||||
s_hSecDll = LoadLibrary("secur32.dll");
|
||||
if(s_hSecDll != NULL) {
|
||||
INIT_SECURITY_INTERFACE pInitSecurityInterface;
|
||||
pInitSecurityInterface =
|
||||
(INIT_SECURITY_INTERFACE)GetProcAddress(s_hSecDll,
|
||||
"InitSecurityInterfaceA");
|
||||
if(pInitSecurityInterface != NULL)
|
||||
s_pSecFn = pInitSecurityInterface();
|
||||
}
|
||||
}
|
||||
if(s_pSecFn == NULL)
|
||||
return CURLE_RECV_ERROR;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_ntlm_global_cleanup(void)
|
||||
{
|
||||
if(s_hSecDll != NULL) {
|
||||
FreeLibrary(s_hSecDll);
|
||||
s_hSecDll = NULL;
|
||||
s_pSecFn = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USE_NTLM */
|
||||
#endif /* !CURL_DISABLE_HTTP */
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -34,7 +34,7 @@ typedef enum {
|
||||
|
||||
/* this is for ntlm header input */
|
||||
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy,
|
||||
const char *header);
|
||||
const char *header);
|
||||
|
||||
/* this is for creating ntlm header output */
|
||||
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
|
||||
@@ -44,11 +44,6 @@ void Curl_ntlm_cleanup(struct connectdata *conn);
|
||||
#define Curl_ntlm_cleanup(x)
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
CURLcode Curl_ntlm_global_init(void);
|
||||
void Curl_ntlm_global_cleanup(void);
|
||||
#endif
|
||||
|
||||
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
|
||||
|
||||
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
|
||||
|
120
lib/krb5.c
120
lib/krb5.c
@@ -138,9 +138,9 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to,
|
||||
dec.value = (void*)from;
|
||||
dec.length = length;
|
||||
maj = gss_seal(&min, *context,
|
||||
level == prot_private,
|
||||
GSS_C_QOP_DEFAULT,
|
||||
&dec, &state, &enc);
|
||||
level == prot_private,
|
||||
GSS_C_QOP_DEFAULT,
|
||||
&dec, &state, &enc);
|
||||
|
||||
if(maj != GSS_S_COMPLETE)
|
||||
return -1;
|
||||
@@ -178,10 +178,12 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
|
||||
chan.initiator_addrtype = GSS_C_AF_INET;
|
||||
chan.initiator_address.length = l - 4;
|
||||
chan.initiator_address.value = &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
|
||||
chan.initiator_address.value =
|
||||
&((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
|
||||
chan.acceptor_addrtype = GSS_C_AF_INET;
|
||||
chan.acceptor_address.length = l - 4;
|
||||
chan.acceptor_address.value = &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
|
||||
chan.acceptor_address.value =
|
||||
&((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
|
||||
chan.application_data.length = 0;
|
||||
chan.application_data.value = NULL;
|
||||
|
||||
@@ -192,12 +194,12 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
result = Curl_ftpsendf(conn, "AUTH GSSAPI");
|
||||
|
||||
if(result)
|
||||
return -2;
|
||||
return -2;
|
||||
if(Curl_GetFTPResponse(&nread, conn, NULL))
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if(data->state.buffer[0] != '3')
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
gssbuf.value = data->state.buffer;
|
||||
@@ -206,8 +208,8 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
if(maj != GSS_S_COMPLETE) {
|
||||
gss_release_name(&min, &gssname);
|
||||
if(service == srv_host) {
|
||||
Curl_failf(data, "Error importing service name %s", gssbuf.value);
|
||||
return AUTH_ERROR;
|
||||
Curl_failf(data, "Error importing service name %s", gssbuf.value);
|
||||
return AUTH_ERROR;
|
||||
}
|
||||
service = srv_host;
|
||||
continue;
|
||||
@@ -224,69 +226,71 @@ krb5_auth(void *app_data, struct connectdata *conn)
|
||||
do {
|
||||
ret = AUTH_OK;
|
||||
maj = gss_init_sec_context(&min,
|
||||
GSS_C_NO_CREDENTIAL,
|
||||
context,
|
||||
gssname,
|
||||
GSS_C_NO_OID,
|
||||
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
|
||||
0,
|
||||
&chan,
|
||||
gssresp,
|
||||
NULL,
|
||||
&gssbuf,
|
||||
NULL,
|
||||
NULL);
|
||||
GSS_C_NO_CREDENTIAL,
|
||||
context,
|
||||
gssname,
|
||||
GSS_C_NO_OID,
|
||||
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
|
||||
0,
|
||||
&chan,
|
||||
gssresp,
|
||||
NULL,
|
||||
&gssbuf,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if(gssresp) {
|
||||
free(_gssresp.value);
|
||||
gssresp = NULL;
|
||||
free(_gssresp.value);
|
||||
gssresp = NULL;
|
||||
}
|
||||
|
||||
if(maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
|
||||
Curl_infof(data, "Error creating security context");
|
||||
ret = AUTH_ERROR;
|
||||
break;
|
||||
Curl_infof(data, "Error creating security context");
|
||||
ret = AUTH_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if(gssbuf.length != 0) {
|
||||
if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p) < 1) {
|
||||
Curl_infof(data, "Out of memory base64-encoding");
|
||||
ret = AUTH_CONTINUE;
|
||||
break;
|
||||
}
|
||||
if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p)
|
||||
< 1) {
|
||||
Curl_infof(data, "Out of memory base64-encoding");
|
||||
ret = AUTH_CONTINUE;
|
||||
break;
|
||||
}
|
||||
|
||||
result = Curl_ftpsendf(conn, "ADAT %s", p);
|
||||
result = Curl_ftpsendf(conn, "ADAT %s", p);
|
||||
|
||||
free(p);
|
||||
free(p);
|
||||
|
||||
if(result) {
|
||||
ret = -2;
|
||||
break;
|
||||
}
|
||||
if(result) {
|
||||
ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if(Curl_GetFTPResponse(&nread, conn, NULL)) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if(Curl_GetFTPResponse(&nread, conn, NULL)) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
|
||||
Curl_infof(data, "Server didn't accept auth data\n");
|
||||
ret = AUTH_ERROR;
|
||||
break;
|
||||
}
|
||||
if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
|
||||
Curl_infof(data, "Server didn't accept auth data\n");
|
||||
ret = AUTH_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
p = data->state.buffer + 4;
|
||||
p = strstr(p, "ADAT=");
|
||||
if(p) {
|
||||
_gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)&_gssresp.value);
|
||||
if(_gssresp.length < 1) {
|
||||
Curl_failf(data, "Out of memory base64-encoding");
|
||||
ret = AUTH_CONTINUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p = data->state.buffer + 4;
|
||||
p = strstr(p, "ADAT=");
|
||||
if(p) {
|
||||
_gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)
|
||||
&_gssresp.value);
|
||||
if(_gssresp.length < 1) {
|
||||
Curl_failf(data, "Out of memory base64-encoding");
|
||||
ret = AUTH_CONTINUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gssresp = &_gssresp;
|
||||
gssresp = &_gssresp;
|
||||
}
|
||||
} while(maj == GSS_S_CONTINUE_NEEDED);
|
||||
|
||||
|
@@ -3,7 +3,7 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "curllib"=".\curllib.dsp" - Package Owner=<4>
|
||||
Project: "libcurl"=".\libcurl.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
@@ -1,139 +0,0 @@
|
||||
# to build Mac OS X framework call the following line with the directory set
|
||||
# properly to lib:
|
||||
# make build -e -f libcurl.framework.make
|
||||
TMP_DIR = ../lib/.lib
|
||||
LIB_DIR = ../lib
|
||||
|
||||
# Sets the SDK. 10.4u.sdk is the minimum for building a Universal Binary.
|
||||
SDK = /Developer/SDKs/MacOSX10.4u.sdk
|
||||
|
||||
# Sets the minimum OSX version where the framework will work.
|
||||
ENVP = MACOSX_DEPLOYMENT_TARGET=10.3
|
||||
|
||||
# for debug symbols add the -g option. Remove the -O2 option for best debugging.
|
||||
# Can be compiled with -O3 optimizations.
|
||||
C_OPTIONS = -isysroot $(SDK) \
|
||||
-fno-common \
|
||||
-Os \
|
||||
-DHAVE_CONFIG_H \
|
||||
-DPIC \
|
||||
-I../lib \
|
||||
-I../include \
|
||||
-Wall \
|
||||
-arch ppc \
|
||||
-arch i386
|
||||
|
||||
LIBRARIES = $(SDK)/usr/lib/libssl.dylib \
|
||||
$(SDK)/usr/lib/libcrypto.dylib \
|
||||
-lz
|
||||
|
||||
# These libtool options are needed for a framework.
|
||||
# @executable_path tells the application that links to this library where to find it.
|
||||
# On Mac OS X frameworks are usually iniside the application bundle in a frameworks folder.
|
||||
# Define a seg1addr so prebinding does not overlap with other frameworks or bundles.
|
||||
# For prebinding 0x10400000 was chosen a bit at random.
|
||||
# If this overlaps one of you current libs just change in the makefile.
|
||||
# This address is safe for all built in frameworks.
|
||||
LINK_OPTIONS = \
|
||||
-Wl,-syslibroot,$(SDK) \
|
||||
-arch ppc \
|
||||
-arch i386 \
|
||||
-prebind \
|
||||
-seg1addr 0x10400000 \
|
||||
-dynamiclib \
|
||||
-install_name @executable_path/../Frameworks/libcurl.framework/libcurl
|
||||
|
||||
# This is the file list. It is not dynamically generated so this must be updated if new files are added to the build.
|
||||
OBJECTS = $(TMP_DIR)/base64.o \
|
||||
$(TMP_DIR)/connect.o \
|
||||
$(TMP_DIR)/content_encoding.o \
|
||||
$(TMP_DIR)/cookie.o \
|
||||
$(TMP_DIR)/curl_addrinfo.o \
|
||||
$(TMP_DIR)/dict.o \
|
||||
$(TMP_DIR)/easy.o \
|
||||
$(TMP_DIR)/escape.o \
|
||||
$(TMP_DIR)/file.o \
|
||||
$(TMP_DIR)/formdata.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 \
|
||||
$(TMP_DIR)/hostip.o \
|
||||
$(TMP_DIR)/hostip4.o \
|
||||
$(TMP_DIR)/hostip6.o \
|
||||
$(TMP_DIR)/hostsyn.o \
|
||||
$(TMP_DIR)/hostthre.o \
|
||||
$(TMP_DIR)/http.o \
|
||||
$(TMP_DIR)/http_chunks.o \
|
||||
$(TMP_DIR)/http_digest.o \
|
||||
$(TMP_DIR)/http_negotiate.o \
|
||||
$(TMP_DIR)/http_ntlm.o \
|
||||
$(TMP_DIR)/if2ip.o \
|
||||
$(TMP_DIR)/inet_ntop.o \
|
||||
$(TMP_DIR)/inet_pton.o \
|
||||
$(TMP_DIR)/krb4.o \
|
||||
$(TMP_DIR)/ldap.o \
|
||||
$(TMP_DIR)/llist.o \
|
||||
$(TMP_DIR)/md5.o \
|
||||
$(TMP_DIR)/memdebug.o \
|
||||
$(TMP_DIR)/mprintf.o \
|
||||
$(TMP_DIR)/multi.o \
|
||||
$(TMP_DIR)/netrc.o \
|
||||
$(TMP_DIR)/parsedate.o \
|
||||
$(TMP_DIR)/progress.o \
|
||||
$(TMP_DIR)/rawstr.o \
|
||||
$(TMP_DIR)/security.o \
|
||||
$(TMP_DIR)/select.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 \
|
||||
$(TMP_DIR)/strtok.o \
|
||||
$(TMP_DIR)/strtoofft.o \
|
||||
$(TMP_DIR)/telnet.o \
|
||||
$(TMP_DIR)/tftp.o \
|
||||
$(TMP_DIR)/timeval.o \
|
||||
$(TMP_DIR)/transfer.o \
|
||||
$(TMP_DIR)/url.o \
|
||||
$(TMP_DIR)/version.o \
|
||||
$(TMP_DIR)/splay.o \
|
||||
$(TMP_DIR)/socks.o
|
||||
|
||||
build: $(TMP_DIR) $(LIB_DIR) $(LIB_DIR)/libcurl.framework
|
||||
|
||||
$(TMP_DIR) :
|
||||
mkdir -p $(TMP_DIR)
|
||||
|
||||
$(LIB_DIR) :
|
||||
mkdir -p $(LIB_DIR)
|
||||
|
||||
# This builds the framework structure and links everything properly
|
||||
$(LIB_DIR)/libcurl.framework: $(OBJECTS) $(LIB_DIR)/libcurl.plist
|
||||
mkdir -p $(LIB_DIR)/libcurl.framework/Versions/A/Resources
|
||||
$(ENVP) $(CC) $(LINK_OPTIONS) $(LIBRARIES) $(OBJECTS) \
|
||||
-o $(LIB_DIR)/libcurl.framework/Versions/A/libcurl
|
||||
cp $(LIB_DIR)/libcurl.plist $(LIB_DIR)/libcurl.framework/Versions/A/Resources/Info.plist
|
||||
mkdir -p $(LIB_DIR)/libcurl.framework/Versions/A/Headers
|
||||
cp $(LIB_DIR)/../include/curl/*.h $(LIB_DIR)/libcurl.framework/Versions/A/Headers
|
||||
cd $(LIB_DIR)/libcurl.framework; \
|
||||
ln -fs Versions/A/libcurl libcurl; \
|
||||
ln -fs Versions/A/Resources Resources; \
|
||||
ln -fs Versions/A/Headers Headers
|
||||
cd $(LIB_DIR)/libcurl.framework/Versions; \
|
||||
ln -fs A Current
|
||||
|
||||
$(OBJECTS) : $(TMP_DIR)/%.o: $(LIB_DIR)/%.c
|
||||
$(CC) $(C_OPTIONS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -fr $(LIB_DIR)/libcurl.framework
|
||||
rm -f $(OBJECTS)
|
||||
|
||||
|
||||
|
24
lib/md5.c
24
lib/md5.c
@@ -27,6 +27,24 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "curl_md5.h"
|
||||
|
||||
#ifdef USE_GNUTLS
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
|
||||
const unsigned char *input)
|
||||
{
|
||||
gcry_md_hd_t ctx;
|
||||
gcry_md_open(&ctx, GCRY_MD_MD5, 0);
|
||||
gcry_md_write(ctx, input, (unsigned int)strlen((char *)input));
|
||||
memcpy (outbuffer, gcry_md_read (ctx, 0), 16);
|
||||
gcry_md_close(ctx);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
/* When OpenSSL is available we use the MD5-function from OpenSSL */
|
||||
|
||||
@@ -341,8 +359,6 @@ static void Decode (UINT4 *output,
|
||||
|
||||
#endif /* USE_SSLEAY */
|
||||
|
||||
#include "curl_md5.h"
|
||||
|
||||
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
|
||||
const unsigned char *input)
|
||||
{
|
||||
@@ -352,4 +368,6 @@ void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
|
||||
MD5_Final(outbuffer, &ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* USE_GNUTLS */
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
|
@@ -1,27 +1,27 @@
|
||||
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Project File - Name="libcurl" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=curllib - Win32 LIB Debug
|
||||
CFG=libcurl - Win32 LIB Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "curllib.mak".
|
||||
!MESSAGE NMAKE /f "libcurl.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 LIB Debug"
|
||||
!MESSAGE NMAKE /f "libcurl.mak" CFG="libcurl - Win32 LIB Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "curllib - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "curllib - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "curllib - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "curllib - Win32 LIB Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "libcurl - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "libcurl - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "libcurl - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "libcurl - Win32 LIB Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
@@ -29,7 +29,7 @@ CFG=curllib - Win32 LIB Debug
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
|
||||
!IF "$(CFG)" == "curllib - Win32 DLL Debug"
|
||||
!IF "$(CFG)" == "libcurl - Win32 DLL Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
@@ -58,7 +58,7 @@ LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib ws2_32.lib wldap32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"DLL-Debug/libcurld.dll" /implib:"DLL-Debug/libcurld_imp.lib" /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib wldap32.lib /nologo /dll /incremental:no /map /debug /machine:I386 /out:"DLL-Debug/libcurld.dll" /implib:"DLL-Debug/libcurld_imp.lib" /pdbtype:sept
|
||||
|
||||
!ELSEIF "$(CFG)" == "curllib - Win32 DLL Release"
|
||||
!ELSEIF "$(CFG)" == "libcurl - Win32 DLL Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
@@ -87,7 +87,7 @@ LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib ws2_32.lib wldap32.lib /nologo /dll /pdb:none /machine:I386 /out:"DLL-Release/libcurl.dll" /implib:"DLL-Release/libcurl_imp.lib"
|
||||
# ADD LINK32 kernel32.lib ws2_32.lib wldap32.lib /nologo /dll /pdb:none /machine:I386 /out:"DLL-Release/libcurl.dll" /implib:"DLL-Release/libcurl_imp.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "curllib - Win32 LIB Debug"
|
||||
!ELSEIF "$(CFG)" == "libcurl - Win32 LIB Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
@@ -112,7 +112,7 @@ LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo /out:"LIB-Debug/libcurld.lib" /machine:I386
|
||||
# ADD LIB32 /nologo /out:"LIB-Debug/libcurld.lib" /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "curllib - Win32 LIB Release"
|
||||
!ELSEIF "$(CFG)" == "libcurl - Win32 LIB Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
@@ -141,7 +141,7 @@ LIB32=link.exe -lib
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "curllib - Win32 DLL Debug"
|
||||
# Name "curllib - Win32 DLL Release"
|
||||
# Name "curllib - Win32 LIB Debug"
|
||||
# Name "curllib - Win32 LIB Release"
|
||||
# Name "libcurl - Win32 DLL Debug"
|
||||
# Name "libcurl - Win32 DLL Release"
|
||||
# Name "libcurl - Win32 LIB Debug"
|
||||
# Name "libcurl - Win32 LIB Release"
|
||||
|
38
lib/multi.c
38
lib/multi.c
@@ -646,7 +646,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
}
|
||||
|
||||
/* If this easy_handle was the last one in charge for one or more
|
||||
connections a the shared connection cache, we might need to keep this
|
||||
connections in the shared connection cache, we might need to keep this
|
||||
handle around until either A) the connection is closed and killed
|
||||
properly, or B) another easy_handle uses the connection.
|
||||
|
||||
@@ -1237,14 +1237,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
break;
|
||||
|
||||
case CURLM_STATE_WAITPERFORM:
|
||||
#ifdef CURLDEBUG
|
||||
infof(easy->easy_handle, "Conn %d recv pipe %d inuse %d athead %d\n",
|
||||
easy->easy_conn->connectindex,
|
||||
easy->easy_conn->recv_pipe->size,
|
||||
easy->easy_conn->readchannel_inuse,
|
||||
isHandleAtHead(easy->easy_handle,
|
||||
easy->easy_conn->recv_pipe));
|
||||
#endif
|
||||
/* Wait for our turn to PERFORM */
|
||||
if(!easy->easy_conn->readchannel_inuse &&
|
||||
isHandleAtHead(easy->easy_handle,
|
||||
@@ -1254,6 +1246,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
multistate(easy, CURLM_STATE_PERFORM);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
#ifdef CURLDEBUG
|
||||
else {
|
||||
infof(easy->easy_handle, "Conn %d recv pipe %d inuse %d athead %d\n",
|
||||
easy->easy_conn->connectindex,
|
||||
easy->easy_conn->recv_pipe->size,
|
||||
easy->easy_conn->readchannel_inuse,
|
||||
isHandleAtHead(easy->easy_handle,
|
||||
easy->easy_conn->recv_pipe));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
|
||||
@@ -1302,18 +1304,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
|
||||
if(easy->result) {
|
||||
/* The transfer phase returned error, we mark the connection to get
|
||||
* closed to prevent being re-used. This is because we can't
|
||||
* possibly know if the connection is in a good shape or not now. */
|
||||
easy->easy_conn->bits.close = TRUE;
|
||||
Curl_removeHandleFromPipeline(easy->easy_handle,
|
||||
easy->easy_conn->recv_pipe);
|
||||
* closed to prevent being re-used. This is because we can't possibly
|
||||
* know if the connection is in a good shape or not now. Unless it is
|
||||
* a protocol which uses two "channels" like FTP, as then the error
|
||||
* happened in the data connection.
|
||||
*/
|
||||
if(!(easy->easy_conn->protocol & PROT_DUALCHANNEL))
|
||||
easy->easy_conn->bits.close = TRUE;
|
||||
|
||||
if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) {
|
||||
/* if we failed anywhere, we must clean up the secondary socket if
|
||||
it was used */
|
||||
sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
|
||||
easy->easy_conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
}
|
||||
Curl_posttransfer(easy->easy_handle);
|
||||
Curl_done(&easy->easy_conn, easy->result, FALSE);
|
||||
}
|
||||
|
@@ -455,7 +455,7 @@ static int nss_load_crl(const char* crlfilename, PRBool ascii)
|
||||
NULL,SEC_CRL_TYPE,
|
||||
NULL,CRL_IMPORT_DEFAULT_OPTIONS,
|
||||
NULL,(CRL_DECODE_DEFAULT_OPTIONS|
|
||||
CRL_DECODE_DONT_COPY_DER));
|
||||
CRL_DECODE_DONT_COPY_DER));
|
||||
if (slot) PK11_FreeSlot(slot);
|
||||
if (!crl) return 0;
|
||||
SEC_DestroyCrl(crl);
|
||||
@@ -1140,7 +1140,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
n = strrchr(data->set.str[STRING_CERT], '/');
|
||||
if(n) {
|
||||
n++; /* skip last slash */
|
||||
nickname = aprintf(nickname, "PEM Token #%d:%s", 1, n);
|
||||
nickname = aprintf("PEM Token #%d:%s", 1, n);
|
||||
if(!nickname)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -1171,7 +1171,8 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
|
||||
if(SSL_GetClientAuthDataHook(model,
|
||||
(SSLGetClientAuthData) SelectClientCert,
|
||||
(void *)connssl) != SECSuccess) {
|
||||
(void *)connssl->client_nickname) !=
|
||||
SECSuccess) {
|
||||
curlerr = CURLE_SSL_CERTPROBLEM;
|
||||
goto error;
|
||||
}
|
||||
|
31
lib/rawstr.c
31
lib/rawstr.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
#include "rawstr.h"
|
||||
|
||||
/* Portable toupper (remember EBCDIC). Do not use tupper() because
|
||||
/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
|
||||
its behavior is altered by the current locale. */
|
||||
static unsigned char my_toupper(unsigned char in)
|
||||
char Curl_raw_toupper(char in)
|
||||
{
|
||||
switch (in) {
|
||||
case 'a':
|
||||
@@ -92,13 +92,14 @@ static unsigned char my_toupper(unsigned char in)
|
||||
* this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
|
||||
* some further explanation to why this function is necessary.
|
||||
*
|
||||
* The function is capable of comparing a-z case insensitively even for non-ascii.
|
||||
* The function is capable of comparing a-z case insensitively even for
|
||||
* non-ascii.
|
||||
*/
|
||||
|
||||
int Curl_raw_equal(const char *first, const char *second)
|
||||
{
|
||||
while(*first && *second) {
|
||||
if(my_toupper(*first) != my_toupper(*second))
|
||||
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
|
||||
/* get out of the loop as soon as they don't match */
|
||||
break;
|
||||
first++;
|
||||
@@ -107,13 +108,13 @@ int Curl_raw_equal(const char *first, const char *second)
|
||||
/* we do the comparison here (possibly again), just to make sure that if the
|
||||
loop above is skipped because one of the strings reached zero, we must not
|
||||
return this as a successful match */
|
||||
return (my_toupper(*first) == my_toupper(*second));
|
||||
return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
|
||||
}
|
||||
|
||||
int Curl_raw_nequal(const char *first, const char *second, size_t max)
|
||||
{
|
||||
while(*first && *second && max) {
|
||||
if(my_toupper(*first) != my_toupper(*second)) {
|
||||
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
|
||||
break;
|
||||
}
|
||||
max--;
|
||||
@@ -123,6 +124,20 @@ int Curl_raw_nequal(const char *first, const char *second, size_t max)
|
||||
if(0 == max)
|
||||
return 1; /* they are equal this far */
|
||||
|
||||
return my_toupper(*first) == my_toupper(*second);
|
||||
return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
|
||||
}
|
||||
|
||||
/* Copy an upper case version of the string from src to dest. The
|
||||
* strings may overlap. No more than n characters of the string are copied
|
||||
* (including any NUL) and the destination string will NOT be
|
||||
* NUL-terminated if that limit is reached.
|
||||
*/
|
||||
void Curl_strntoupper(char *dest, const char *src, size_t n)
|
||||
{
|
||||
if (n < 1)
|
||||
return;
|
||||
|
||||
do {
|
||||
*dest++ = Curl_raw_toupper(*src);
|
||||
} while (*src++ && --n);
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -35,8 +35,11 @@
|
||||
int Curl_raw_equal(const char *first, const char *second);
|
||||
int Curl_raw_nequal(const char *first, const char *second, size_t max);
|
||||
|
||||
char Curl_raw_toupper(char in);
|
||||
|
||||
/* checkprefix() is a shorter version of the above, used when the first
|
||||
argument is zero-byte terminated */
|
||||
#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a))
|
||||
|
||||
#endif
|
||||
void Curl_strntoupper(char *dest, const char *src, size_t n);
|
||||
|
@@ -455,7 +455,7 @@ int netware_init(void);
|
||||
#endif
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
|
||||
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
|
||||
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || defined(USE_GNUTLS)
|
||||
#define USE_NTLM
|
||||
#endif
|
||||
#endif
|
||||
|
78
lib/socks.c
78
lib/socks.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -60,14 +60,14 @@
|
||||
* This is STUPID BLOCKING behaviour which we frown upon, but right now this
|
||||
* is what we have...
|
||||
*/
|
||||
static int blockread_all(struct connectdata *conn, /* connection data */
|
||||
curl_socket_t sockfd, /* read from this socket */
|
||||
char *buf, /* store read data here */
|
||||
ssize_t buffersize, /* max amount to read */
|
||||
ssize_t *n, /* amount bytes read */
|
||||
long conn_timeout) /* timeout for data wait
|
||||
relative to
|
||||
conn->created */
|
||||
int Curl_blockread_all(struct connectdata *conn, /* connection data */
|
||||
curl_socket_t sockfd, /* read from this socket */
|
||||
char *buf, /* store read data here */
|
||||
ssize_t buffersize, /* max amount to read */
|
||||
ssize_t *n, /* amount bytes read */
|
||||
long conn_timeout) /* timeout for data wait
|
||||
relative to
|
||||
conn->created */
|
||||
{
|
||||
ssize_t nread;
|
||||
ssize_t allread = 0;
|
||||
@@ -264,7 +264,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
packetsize = 8; /* receive data size */
|
||||
|
||||
/* Receive response */
|
||||
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
|
||||
result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
|
||||
&actualread, timeout);
|
||||
if((result != CURLE_OK) || (actualread != packetsize)) {
|
||||
failf(data, "Failed to receive SOCKS4 connect request ack.");
|
||||
@@ -429,9 +429,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
}
|
||||
|
||||
socksreq[0] = 5; /* version */
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
socksreq[1] = (char)(proxy_name ? 3 : 2); /* number of methods (below) */
|
||||
socksreq[2] = 0; /* no authentication */
|
||||
socksreq[3] = 1; /* gssapi */
|
||||
socksreq[4] = 2; /* username/password */
|
||||
#else
|
||||
socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
|
||||
socksreq[2] = 0; /* no authentication */
|
||||
socksreq[3] = 2; /* username/password */
|
||||
#endif
|
||||
|
||||
Curl_nonblock(sock, FALSE);
|
||||
|
||||
@@ -462,7 +469,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
|
||||
Curl_nonblock(sock, FALSE);
|
||||
|
||||
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread, timeout);
|
||||
result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
|
||||
timeout);
|
||||
if((result != CURLE_OK) || (actualread != 2)) {
|
||||
failf(data, "Unable to receive initial SOCKS5 response.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
@@ -476,6 +484,15 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
/* Nothing to do, no authentication needed */
|
||||
;
|
||||
}
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
else if(socksreq[1] == 1) {
|
||||
code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
|
||||
if(code != CURLE_OK) {
|
||||
failf(data, "Unable to negotiate SOCKS5 gssapi context.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if(socksreq[1] == 2) {
|
||||
/* Needs user name and password */
|
||||
size_t userlen, pwlen;
|
||||
@@ -511,7 +528,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
|
||||
result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
|
||||
timeout);
|
||||
if((result != CURLE_OK) || (actualread != 2)) {
|
||||
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
|
||||
@@ -529,12 +546,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
}
|
||||
else {
|
||||
/* error */
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(socksreq[1] == 255) {
|
||||
#else
|
||||
if(socksreq[1] == 1) {
|
||||
failf(data,
|
||||
"SOCKS5 GSSAPI per-message authentication is not supported.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
else if(socksreq[1] == 255) {
|
||||
#endif
|
||||
if(!proxy_name || !*proxy_name) {
|
||||
failf(data,
|
||||
"No authentication method was acceptable. (It is quite likely"
|
||||
@@ -616,6 +637,11 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
*((unsigned short*)&socksreq[8]) = htons((unsigned short)remote_port);
|
||||
}
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(conn->socks5_gssapi_enctype) {
|
||||
failf(data, "SOCKS5 gssapi protection not yet implemented.");
|
||||
} else
|
||||
#endif
|
||||
code = Curl_write_plain(conn, sock, (char *)socksreq, packetsize, &written);
|
||||
if((code != CURLE_OK) || (written != packetsize)) {
|
||||
failf(data, "Failed to send SOCKS5 connect request.");
|
||||
@@ -624,7 +650,12 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
|
||||
packetsize = 10; /* minimum packet size is 10 */
|
||||
|
||||
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(conn->socks5_gssapi_enctype) {
|
||||
failf(data, "SOCKS5 gssapi protection not yet implemented.");
|
||||
} else
|
||||
#endif
|
||||
result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
|
||||
&actualread, timeout);
|
||||
if((result != CURLE_OK) || (actualread != packetsize)) {
|
||||
failf(data, "Failed to receive SOCKS5 connect request ack.");
|
||||
@@ -674,15 +705,22 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
}
|
||||
|
||||
/* At this point we already read first 10 bytes */
|
||||
if(packetsize > 10) {
|
||||
packetsize -= 10;
|
||||
result = blockread_all(conn, sock, (char *)&socksreq[10], packetsize,
|
||||
&actualread, timeout);
|
||||
if((result != CURLE_OK) || (actualread != packetsize)) {
|
||||
failf(data, "Failed to receive SOCKS5 connect request ack.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(!conn->socks5_gssapi_enctype) {
|
||||
/* decrypt_gssapi_blockread already read the whole packet */
|
||||
#endif
|
||||
if(packetsize > 10) {
|
||||
packetsize -= 10;
|
||||
result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
|
||||
packetsize, &actualread, timeout);
|
||||
if((result != CURLE_OK) || (actualread != packetsize)) {
|
||||
failf(data, "Failed to receive SOCKS5 connect request ack.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
}
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
}
|
||||
#endif
|
||||
|
||||
Curl_nonblock(sock, TRUE);
|
||||
return CURLE_OK; /* Proxy was successful! */
|
||||
|
24
lib/socks.h
24
lib/socks.h
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -23,6 +23,20 @@
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Helper read-from-socket functions. Does the same as Curl_read() but it
|
||||
* blocks until all bytes amount of buffersize will be read. No more, no less.
|
||||
*
|
||||
* This is STUPID BLOCKING behaviour which we frown upon, but right now this
|
||||
* is what we have...
|
||||
*/
|
||||
int Curl_blockread_all(struct connectdata *conn,
|
||||
curl_socket_t sockfd,
|
||||
char *buf,
|
||||
ssize_t buffersize,
|
||||
ssize_t *n,
|
||||
long conn_timeout);
|
||||
|
||||
/*
|
||||
* This function logs in to a SOCKS4(a) proxy and sends the specifics to the
|
||||
* final destination server.
|
||||
@@ -45,4 +59,12 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
|
||||
int sockindex,
|
||||
struct connectdata *conn);
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
/*
|
||||
* This function handles the sockss5 gssapie negotiation and initialisation
|
||||
*/
|
||||
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
struct connectdata *conn);
|
||||
#endif
|
||||
|
||||
#endif /* __SOCKS_H */
|
||||
|
551
lib/socks_gssapi.c
Normal file
551
lib/socks_gssapi.c
Normal file
@@ -0,0 +1,551 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
|
||||
*
|
||||
* 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$
|
||||
***************************************************************************/
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
#ifdef HAVE_OLD_GSSMIT
|
||||
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
|
||||
#endif
|
||||
#ifndef gss_nt_service_name
|
||||
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NEED_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "connect.h"
|
||||
#include "timeval.h"
|
||||
#include "socks.h"
|
||||
|
||||
static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Helper gssapi error functions.
|
||||
*/
|
||||
static int check_gss_err(struct SessionHandle *data,
|
||||
OM_uint32 major_status,
|
||||
OM_uint32 minor_status,
|
||||
const char* function)
|
||||
{
|
||||
if(GSS_ERROR(major_status)) {
|
||||
OM_uint32 maj_stat,min_stat;
|
||||
OM_uint32 msg_ctx = 0;
|
||||
gss_buffer_desc status_string;
|
||||
char buf[1024];
|
||||
size_t len;
|
||||
|
||||
len = 0;
|
||||
msg_ctx = 0;
|
||||
while(!msg_ctx) {
|
||||
/* convert major status code (GSS-API error) to text */
|
||||
maj_stat = gss_display_status(&min_stat, major_status,
|
||||
GSS_C_GSS_CODE,
|
||||
GSS_C_NULL_OID,
|
||||
&msg_ctx, &status_string);
|
||||
if(maj_stat == GSS_S_COMPLETE) {
|
||||
if(sizeof(buf) > len + status_string.length + 1) {
|
||||
strcpy(buf+len, (char*) status_string.value);
|
||||
len += status_string.length;
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
break;
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
}
|
||||
if(sizeof(buf) > len + 3) {
|
||||
strcpy(buf+len, ".\n");
|
||||
len += 2;
|
||||
}
|
||||
msg_ctx = 0;
|
||||
while(!msg_ctx) {
|
||||
/* convert minor status code (underlying routine error) to text */
|
||||
maj_stat = gss_display_status(&min_stat, minor_status,
|
||||
GSS_C_MECH_CODE,
|
||||
GSS_C_NULL_OID,
|
||||
&msg_ctx, &status_string);
|
||||
if(maj_stat == GSS_S_COMPLETE) {
|
||||
if(sizeof(buf) > len + status_string.length) {
|
||||
strcpy(buf+len, (char*) status_string.value);
|
||||
len += status_string.length;
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
break;
|
||||
}
|
||||
gss_release_buffer(&min_stat, &status_string);
|
||||
}
|
||||
failf(data, "GSSAPI error: %s failed:\n%s\n", function, buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
curl_socket_t sock = conn->sock[sockindex];
|
||||
CURLcode code;
|
||||
ssize_t actualread;
|
||||
ssize_t written;
|
||||
int result;
|
||||
long timeout;
|
||||
OM_uint32 gss_major_status, gss_minor_status, gss_status;
|
||||
OM_uint32 gss_ret_flags;
|
||||
int gss_conf_state, gss_enc;
|
||||
gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc* gss_token = GSS_C_NO_BUFFER;
|
||||
gss_name_t server = GSS_C_NO_NAME;
|
||||
gss_name_t gss_client_name = GSS_C_NO_NAME;
|
||||
u_short us_length;
|
||||
char *user=NULL;
|
||||
unsigned char socksreq[4]; /* room for gssapi exchange header only */
|
||||
char *serviceptr = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||
|
||||
/* get timeout */
|
||||
timeout = Curl_timeleft(conn, NULL, TRUE);
|
||||
|
||||
/* GSSAPI request looks like
|
||||
* +----+------+-----+----------------+
|
||||
* |VER | MTYP | LEN | TOKEN |
|
||||
* +----+------+----------------------+
|
||||
* | 1 | 1 | 2 | up to 2^16 - 1 |
|
||||
* +----+------+-----+----------------+
|
||||
*/
|
||||
|
||||
/* prepare service name */
|
||||
if (strchr(serviceptr,'/')) {
|
||||
service.value = malloc(strlen(serviceptr));
|
||||
if(!service.value)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
service.length = strlen(serviceptr);
|
||||
memcpy(service.value, serviceptr, service.length);
|
||||
|
||||
gss_major_status = gss_import_name(&gss_minor_status, &service,
|
||||
(gss_OID) GSS_C_NULL_OID, &server);
|
||||
}
|
||||
else {
|
||||
service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
|
||||
if(!service.value)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
|
||||
snprintf(service.value, service.length+1, "%s@%s",
|
||||
serviceptr, conn->proxy.name);
|
||||
|
||||
gss_major_status = gss_import_name(&gss_minor_status, &service,
|
||||
gss_nt_service_name, &server);
|
||||
}
|
||||
|
||||
gss_release_buffer(&gss_status, &service); /* clear allocated memory */
|
||||
|
||||
if(check_gss_err(data,gss_major_status,
|
||||
gss_minor_status,"gss_import_name()")) {
|
||||
failf(data, "Failed to create service name.");
|
||||
gss_release_name(&gss_status, &server);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* As long as we need to keep sending some context info, and there's no */
|
||||
/* errors, keep sending it... */
|
||||
for(;;) {
|
||||
gss_major_status = gss_init_sec_context(&gss_minor_status,
|
||||
GSS_C_NO_CREDENTIAL,
|
||||
&gss_context, server,
|
||||
GSS_C_NULL_OID,
|
||||
GSS_C_MUTUAL_FLAG |
|
||||
GSS_C_REPLAY_FLAG,
|
||||
0,
|
||||
NULL,
|
||||
gss_token,
|
||||
NULL,
|
||||
&gss_send_token,
|
||||
&gss_ret_flags,
|
||||
NULL);
|
||||
|
||||
if(gss_token != GSS_C_NO_BUFFER)
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
if(check_gss_err(data,gss_major_status,
|
||||
gss_minor_status,"gss_init_sec_context")) {
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
failf(data, "Failed to initial GSSAPI token.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(gss_send_token.length != 0) {
|
||||
socksreq[0] = 1; /* gssapi subnegotiation version */
|
||||
socksreq[1] = 1; /* authentication message type */
|
||||
us_length = htons((short)gss_send_token.length);
|
||||
memcpy(socksreq+2,&us_length,sizeof(short));
|
||||
|
||||
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
|
||||
if((code != CURLE_OK) || (4 != written)) {
|
||||
failf(data, "Failed to send GSSAPI authentication request.");
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
code = Curl_write_plain(conn, sock, (char *)gss_send_token.value,
|
||||
gss_send_token.length, &written);
|
||||
|
||||
if((code != CURLE_OK) || ((ssize_t)gss_send_token.length != written)) {
|
||||
failf(data, "Failed to send GSSAPI authentication token.");
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
if(gss_major_status != GSS_S_CONTINUE_NEEDED) break;
|
||||
|
||||
/* analyse response */
|
||||
|
||||
/* GSSAPI response looks like
|
||||
* +----+------+-----+----------------+
|
||||
* |VER | MTYP | LEN | TOKEN |
|
||||
* +----+------+----------------------+
|
||||
* | 1 | 1 | 2 | up to 2^16 - 1 |
|
||||
* +----+------+-----+----------------+
|
||||
*/
|
||||
|
||||
result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
|
||||
&actualread, timeout);
|
||||
if(result != CURLE_OK || actualread != 4) {
|
||||
failf(data, "Failed to receive GSSAPI authentication response.");
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* ignore the first (VER) byte */
|
||||
if(socksreq[1] == 255) { /* status / message type */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(socksreq[1] != 1) { /* status / messgae type */
|
||||
failf(data, "Invalid GSSAPI authentication response type (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(&us_length, socksreq+2, sizeof(short));
|
||||
us_length = ntohs(us_length);
|
||||
|
||||
gss_recv_token.length=us_length;
|
||||
gss_recv_token.value=malloc(us_length);
|
||||
if(!gss_recv_token.value) {
|
||||
failf(data,
|
||||
"Could not allocate memory for GSSAPI authentication "
|
||||
"response token.");
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
|
||||
gss_recv_token.length,
|
||||
&actualread, timeout);
|
||||
|
||||
if(result != CURLE_OK || actualread != us_length) {
|
||||
failf(data, "Failed to receive GSSAPI authentication token.");
|
||||
gss_release_name(&gss_status, &server);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
gss_token = &gss_recv_token;
|
||||
}
|
||||
|
||||
gss_release_name(&gss_status, &server);
|
||||
|
||||
/* Everything is good so far, user was authenticated! */
|
||||
gss_major_status = gss_inquire_context (&gss_minor_status, gss_context,
|
||||
&gss_client_name, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
if(check_gss_err(data,gss_major_status,
|
||||
gss_minor_status,"gss_inquire_context")) {
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
gss_release_name(&gss_status, &gss_client_name);
|
||||
failf(data, "Failed to determine user name.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
gss_major_status = gss_display_name(&gss_minor_status, gss_client_name,
|
||||
&gss_send_token, NULL);
|
||||
if(check_gss_err(data,gss_major_status,
|
||||
gss_minor_status,"gss_display_name")) {
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
gss_release_name(&gss_status, &gss_client_name);
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
failf(data, "Failed to determine user name.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
user=malloc(gss_send_token.length+1);
|
||||
if(!user) {
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
gss_release_name(&gss_status, &gss_client_name);
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(user, gss_send_token.value, gss_send_token.length);
|
||||
user[gss_send_token.length] = '\0';
|
||||
gss_release_name(&gss_status, &gss_client_name);
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
infof(data, "SOCKS5 server authencticated user %s with gssapi.\n",user);
|
||||
free(user);
|
||||
user=NULL;
|
||||
|
||||
/* Do encryption */
|
||||
socksreq[0] = 1; /* gssapi subnegotiation version */
|
||||
socksreq[1] = 2; /* encryption message type */
|
||||
|
||||
gss_enc = 0; /* no data protection */
|
||||
/* do confidentiality protection if supported */
|
||||
if(gss_ret_flags & GSS_C_CONF_FLAG)
|
||||
gss_enc = 2;
|
||||
/* else do integrity protection */
|
||||
else if(gss_ret_flags & GSS_C_INTEG_FLAG)
|
||||
gss_enc = 1;
|
||||
|
||||
infof(data, "SOCKS5 server supports gssapi %s data protection.\n",
|
||||
(gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
|
||||
/* force for the moment to no data protection */
|
||||
gss_enc = 0;
|
||||
/*
|
||||
* Sending the encryption type in clear seems wrong. It should be
|
||||
* protected with gss_seal()/gss_wrap(). See RFC1961 extract below
|
||||
* The NEC reference implementations on which this is based is
|
||||
* therefore at fault
|
||||
*
|
||||
* +------+------+------+.......................+
|
||||
* + ver | mtyp | len | token |
|
||||
* +------+------+------+.......................+
|
||||
* + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
|
||||
* +------+------+------+.......................+
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* - "ver" is the protocol version number, here 1 to represent the
|
||||
* first version of the SOCKS/GSS-API protocol
|
||||
*
|
||||
* - "mtyp" is the message type, here 2 to represent a protection
|
||||
* -level negotiation message
|
||||
*
|
||||
* - "len" is the length of the "token" field in octets
|
||||
*
|
||||
* - "token" is the GSS-API encapsulated protection level
|
||||
*
|
||||
* The token is produced by encapsulating an octet containing the
|
||||
* required protection level using gss_seal()/gss_wrap() with conf_req
|
||||
* set to FALSE. The token is verified using gss_unseal()/
|
||||
* gss_unwrap().
|
||||
*
|
||||
*/
|
||||
if(data->set.socks5_gssapi_nec) {
|
||||
us_length = htons((short)1);
|
||||
memcpy(socksreq+2,&us_length,sizeof(short));
|
||||
}
|
||||
else {
|
||||
gss_send_token.length = 1;
|
||||
gss_send_token.value = malloc(1);
|
||||
if(!gss_send_token.value) {
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(gss_send_token.value, &gss_enc, 1);
|
||||
|
||||
gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0,
|
||||
GSS_C_QOP_DEFAULT, &gss_send_token,
|
||||
&gss_conf_state, &gss_w_token);
|
||||
|
||||
if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_wrap")) {
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
failf(data, "Failed to wrap GSSAPI encryption value into token.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
gss_release_buffer(&gss_status, &gss_send_token);
|
||||
|
||||
us_length = htons((short)gss_w_token.length);
|
||||
memcpy(socksreq+2,&us_length,sizeof(short));
|
||||
}
|
||||
|
||||
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
|
||||
if((code != CURLE_OK) || (4 != written)) {
|
||||
failf(data, "Failed to send GSSAPI encryption request.");
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(data->set.socks5_gssapi_nec) {
|
||||
memcpy(socksreq, &gss_enc, 1);
|
||||
code = Curl_write_plain(conn, sock, socksreq, 1, &written);
|
||||
if((code != CURLE_OK) || ( 1 != written)) {
|
||||
failf(data, "Failed to send GSSAPI encryption type.");
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
} else {
|
||||
code = Curl_write_plain(conn, sock, (char *)gss_w_token.value,
|
||||
gss_w_token.length, &written);
|
||||
if((code != CURLE_OK) || ((ssize_t)gss_w_token.length != written)) {
|
||||
failf(data, "Failed to send GSSAPI encryption type.");
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
}
|
||||
|
||||
result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
|
||||
&actualread, timeout);
|
||||
if(result != CURLE_OK || actualread != 4) {
|
||||
failf(data, "Failed to receive GSSAPI encryption response.");
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* ignore the first (VER) byte */
|
||||
if(socksreq[1] == 255) { /* status / message type */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(socksreq[1] != 2) { /* status / messgae type */
|
||||
failf(data, "Invalid GSSAPI encryption response type (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(&us_length, socksreq+2, sizeof(short));
|
||||
us_length = ntohs(us_length);
|
||||
|
||||
gss_recv_token.length= us_length;
|
||||
gss_recv_token.value=malloc(gss_recv_token.length);
|
||||
if(!gss_recv_token.value) {
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
|
||||
gss_recv_token.length,
|
||||
&actualread, timeout);
|
||||
|
||||
if(result != CURLE_OK || actualread != us_length) {
|
||||
failf(data, "Failed to receive GSSAPI encryptrion type.");
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(!data->set.socks5_gssapi_nec) {
|
||||
gss_major_status = gss_unwrap(&gss_minor_status, gss_context,
|
||||
&gss_recv_token, &gss_w_token,
|
||||
0, GSS_C_QOP_DEFAULT);
|
||||
|
||||
if(check_gss_err(data,gss_major_status,gss_minor_status,"gss_unwrap")) {
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
failf(data, "Failed to unwrap GSSAPI encryption value into token.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
|
||||
if(gss_w_token.length != 1) {
|
||||
failf(data, "Invalid GSSAPI encryption response length (%d).",
|
||||
gss_w_token.length);
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(socksreq,gss_w_token.value,gss_w_token.length);
|
||||
gss_release_buffer(&gss_status, &gss_w_token);
|
||||
}
|
||||
else {
|
||||
if(gss_recv_token.length != 1) {
|
||||
failf(data, "Invalid GSSAPI encryption response length (%d).",
|
||||
gss_recv_token.length);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(socksreq,gss_recv_token.value,gss_recv_token.length);
|
||||
gss_release_buffer(&gss_status, &gss_recv_token);
|
||||
}
|
||||
|
||||
infof(data, "SOCKS5 access with%s protection granted.\n",
|
||||
(socksreq[0]==0)?"out gssapi data":
|
||||
((socksreq[0]==1)?" gssapi integrity":" gssapi confidentiality"));
|
||||
|
||||
conn->socks5_gssapi_enctype = socksreq[0];
|
||||
if(socksreq[0] == 0)
|
||||
gss_delete_sec_context(&gss_status, &gss_context, NULL);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CURL_DISABLE_PROXY */
|
699
lib/socks_sspi.c
Normal file
699
lib/socks_sspi.c
Normal file
@@ -0,0 +1,699 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
|
||||
*
|
||||
* 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$
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "setup.h"
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef NEED_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "connect.h"
|
||||
#include "timeval.h"
|
||||
#include "socks.h"
|
||||
#include "curl_sspi.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Definitions required from ntsecapi.h are directly provided below this point
|
||||
* to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h
|
||||
*/
|
||||
#define KERB_WRAP_NO_ENCRYPT 0x80000001
|
||||
|
||||
/*
|
||||
* Helper sspi error functions.
|
||||
*/
|
||||
static int check_sspi_err(struct SessionHandle *data,
|
||||
SECURITY_STATUS major_status,
|
||||
SECURITY_STATUS minor_status,
|
||||
const char* function)
|
||||
{
|
||||
const char *txt;
|
||||
(void)minor_status;
|
||||
|
||||
if(major_status != SEC_E_OK &&
|
||||
major_status != SEC_I_COMPLETE_AND_CONTINUE &&
|
||||
major_status != SEC_I_COMPLETE_NEEDED &&
|
||||
major_status != SEC_I_CONTINUE_NEEDED) {
|
||||
failf(data, "SSPI error: %s failed: %d\n", function, major_status);
|
||||
switch (major_status) {
|
||||
case SEC_I_COMPLETE_AND_CONTINUE:
|
||||
txt="SEC_I_COMPLETE_AND_CONTINUE";
|
||||
break;
|
||||
case SEC_I_COMPLETE_NEEDED:
|
||||
txt="SEC_I_COMPLETE_NEEDED";
|
||||
break;
|
||||
case SEC_I_CONTINUE_NEEDED:
|
||||
txt="SEC_I_CONTINUE_NEEDED";
|
||||
break;
|
||||
case SEC_I_CONTEXT_EXPIRED:
|
||||
txt="SEC_I_CONTEXT_EXPIRED";
|
||||
break;
|
||||
case SEC_I_INCOMPLETE_CREDENTIALS:
|
||||
txt="SEC_I_INCOMPLETE_CREDENTIALS";
|
||||
break;
|
||||
case SEC_I_RENEGOTIATE:
|
||||
txt="SEC_I_RENEGOTIATE";
|
||||
break;
|
||||
case SEC_E_BUFFER_TOO_SMALL:
|
||||
txt="SEC_E_BUFFER_TOO_SMALL";
|
||||
break;
|
||||
case SEC_E_CONTEXT_EXPIRED:
|
||||
txt="SEC_E_CONTEXT_EXPIRED";
|
||||
break;
|
||||
case SEC_E_CRYPTO_SYSTEM_INVALID:
|
||||
txt="SEC_E_CRYPTO_SYSTEM_INVALID";
|
||||
break;
|
||||
case SEC_E_INCOMPLETE_MESSAGE:
|
||||
txt="SEC_E_INCOMPLETE_MESSAGE";
|
||||
break;
|
||||
case SEC_E_INSUFFICIENT_MEMORY:
|
||||
txt="SEC_E_INSUFFICIENT_MEMORY";
|
||||
break;
|
||||
case SEC_E_INTERNAL_ERROR:
|
||||
txt="SEC_E_INTERNAL_ERROR";
|
||||
break;
|
||||
case SEC_E_INVALID_HANDLE:
|
||||
txt="SEC_E_INVALID_HANDLE";
|
||||
break;
|
||||
case SEC_E_INVALID_TOKEN:
|
||||
txt="SEC_E_INVALID_TOKEN";
|
||||
break;
|
||||
case SEC_E_LOGON_DENIED:
|
||||
txt="SEC_E_LOGON_DENIED";
|
||||
break;
|
||||
case SEC_E_MESSAGE_ALTERED:
|
||||
txt="SEC_E_MESSAGE_ALTERED";
|
||||
break;
|
||||
case SEC_E_NO_AUTHENTICATING_AUTHORITY:
|
||||
txt="SEC_E_NO_AUTHENTICATING_AUTHORITY";
|
||||
break;
|
||||
case SEC_E_NO_CREDENTIALS:
|
||||
txt="SEC_E_NO_CREDENTIALS";
|
||||
break;
|
||||
case SEC_E_NOT_OWNER:
|
||||
txt="SEC_E_NOT_OWNER";
|
||||
break;
|
||||
case SEC_E_OUT_OF_SEQUENCE:
|
||||
txt="SEC_E_OUT_OF_SEQUENCE";
|
||||
break;
|
||||
case SEC_E_QOP_NOT_SUPPORTED:
|
||||
txt="SEC_E_QOP_NOT_SUPPORTED";
|
||||
break;
|
||||
case SEC_E_SECPKG_NOT_FOUND:
|
||||
txt="SEC_E_SECPKG_NOT_FOUND";
|
||||
break;
|
||||
case SEC_E_TARGET_UNKNOWN:
|
||||
txt="SEC_E_TARGET_UNKNOWN";
|
||||
break;
|
||||
case SEC_E_UNKNOWN_CREDENTIALS:
|
||||
txt="SEC_E_UNKNOWN_CREDENTIALS";
|
||||
break;
|
||||
case SEC_E_UNSUPPORTED_FUNCTION:
|
||||
txt="SEC_E_UNSUPPORTED_FUNCTION";
|
||||
break;
|
||||
case SEC_E_WRONG_PRINCIPAL:
|
||||
txt="SEC_E_WRONG_PRINCIPAL";
|
||||
break;
|
||||
default:
|
||||
txt="Unknown error";
|
||||
|
||||
}
|
||||
failf(data, "SSPI error: %s failed: %s\n", function, txt);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the SSPI-using version of this function */
|
||||
CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
curl_socket_t sock = conn->sock[sockindex];
|
||||
CURLcode code;
|
||||
ssize_t actualread;
|
||||
ssize_t written;
|
||||
int result;
|
||||
long timeout;
|
||||
/* Needs GSSAPI authentication */
|
||||
SECURITY_STATUS sspi_major_status, sspi_minor_status=0;
|
||||
unsigned long sspi_ret_flags=0;
|
||||
int gss_enc;
|
||||
SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
|
||||
SecBufferDesc input_desc, output_desc, wrap_desc;
|
||||
SecPkgContext_Sizes sspi_sizes;
|
||||
CredHandle cred_handle;
|
||||
CtxtHandle sspi_context;
|
||||
PCtxtHandle context_handle = NULL;
|
||||
SecPkgCredentials_Names names;
|
||||
TimeStamp expiry;
|
||||
char *service_name=NULL;
|
||||
u_short us_length;
|
||||
ULONG qop;
|
||||
unsigned char socksreq[4]; /* room for gssapi exchange header only */
|
||||
char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
|
||||
|
||||
/* get timeout */
|
||||
timeout = Curl_timeleft(conn, NULL, TRUE);
|
||||
|
||||
/* GSSAPI request looks like
|
||||
* +----+------+-----+----------------+
|
||||
* |VER | MTYP | LEN | TOKEN |
|
||||
* +----+------+----------------------+
|
||||
* | 1 | 1 | 2 | up to 2^16 - 1 |
|
||||
* +----+------+-----+----------------+
|
||||
*/
|
||||
|
||||
/* prepare service name */
|
||||
if (strchr(service, '/')) {
|
||||
service_name = malloc(strlen(service));
|
||||
if(!service_name)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
memcpy(service_name, service, strlen(service));
|
||||
}
|
||||
else {
|
||||
service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
|
||||
if(!service_name)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
snprintf(service_name,strlen(service) +strlen(conn->proxy.name)+2,"%s/%s",
|
||||
service,conn->proxy.name);
|
||||
}
|
||||
|
||||
input_desc.cBuffers = 1;
|
||||
input_desc.pBuffers = &sspi_recv_token;
|
||||
input_desc.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
sspi_recv_token.BufferType = SECBUFFER_TOKEN;
|
||||
sspi_recv_token.cbBuffer = 0;
|
||||
sspi_recv_token.pvBuffer = NULL;
|
||||
|
||||
output_desc.cBuffers = 1;
|
||||
output_desc.pBuffers = &sspi_send_token;
|
||||
output_desc.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
sspi_send_token.BufferType = SECBUFFER_TOKEN;
|
||||
sspi_send_token.cbBuffer = 0;
|
||||
sspi_send_token.pvBuffer = NULL;
|
||||
|
||||
wrap_desc.cBuffers = 3;
|
||||
wrap_desc.pBuffers = sspi_w_token;
|
||||
wrap_desc.ulVersion = SECBUFFER_VERSION;
|
||||
|
||||
cred_handle.dwLower = 0;
|
||||
cred_handle.dwUpper = 0;
|
||||
|
||||
sspi_major_status = s_pSecFn->AcquireCredentialsHandleA( NULL,
|
||||
(char *)"Kerberos",
|
||||
SECPKG_CRED_OUTBOUND,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&cred_handle,
|
||||
&expiry);
|
||||
|
||||
if(check_sspi_err(data, sspi_major_status,sspi_minor_status,
|
||||
"AcquireCredentialsHandleA") ) {
|
||||
failf(data, "Failed to acquire credentials.");
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* As long as we need to keep sending some context info, and there's no */
|
||||
/* errors, keep sending it... */
|
||||
for(;;) {
|
||||
|
||||
sspi_major_status = s_pSecFn->InitializeSecurityContextA(
|
||||
&cred_handle,
|
||||
context_handle,
|
||||
service_name,
|
||||
ISC_REQ_MUTUAL_AUTH |
|
||||
ISC_REQ_ALLOCATE_MEMORY |
|
||||
ISC_REQ_CONFIDENTIALITY |
|
||||
ISC_REQ_REPLAY_DETECT,
|
||||
0,
|
||||
SECURITY_NATIVE_DREP,
|
||||
&input_desc,
|
||||
0,
|
||||
&sspi_context,
|
||||
&output_desc,
|
||||
&sspi_ret_flags,
|
||||
&expiry);
|
||||
|
||||
if(sspi_recv_token.pvBuffer) {
|
||||
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
|
||||
sspi_recv_token.pvBuffer = NULL;
|
||||
sspi_recv_token.cbBuffer = 0;
|
||||
}
|
||||
|
||||
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
|
||||
"InitializeSecurityContextA") ){
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
|
||||
failf(data, "Failed to initialise security context.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(sspi_send_token.cbBuffer != 0) {
|
||||
socksreq[0] = 1; /* gssapi subnegotiation version */
|
||||
socksreq[1] = 1; /* authentication message type */
|
||||
us_length = htons((short)sspi_send_token.cbBuffer);
|
||||
memcpy(socksreq+2, &us_length, sizeof(short));
|
||||
|
||||
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
|
||||
if((code != CURLE_OK) || (4 != written)) {
|
||||
failf(data, "Failed to send SSPI authentication request.");
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
|
||||
sspi_send_token.cbBuffer, &written);
|
||||
if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) {
|
||||
failf(data, "Failed to send SSPI authentication token.");
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
|
||||
sspi_send_token.pvBuffer = NULL;
|
||||
sspi_send_token.cbBuffer = 0;
|
||||
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
|
||||
sspi_recv_token.pvBuffer = NULL;
|
||||
sspi_recv_token.cbBuffer = 0;
|
||||
if(sspi_major_status != SEC_I_CONTINUE_NEEDED) break;
|
||||
|
||||
/* analyse response */
|
||||
|
||||
/* GSSAPI response looks like
|
||||
* +----+------+-----+----------------+
|
||||
* |VER | MTYP | LEN | TOKEN |
|
||||
* +----+------+----------------------+
|
||||
* | 1 | 1 | 2 | up to 2^16 - 1 |
|
||||
* +----+------+-----+----------------+
|
||||
*/
|
||||
|
||||
result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
|
||||
&actualread, timeout);
|
||||
if(result != CURLE_OK || actualread != 4) {
|
||||
failf(data, "Failed to receive SSPI authentication response.");
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* ignore the first (VER) byte */
|
||||
if(socksreq[1] == 255) { /* status / message type */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(socksreq[1] != 1) { /* status / messgae type */
|
||||
failf(data, "Invalid SSPI authentication response type (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(&us_length, socksreq+2, sizeof(short));
|
||||
us_length = ntohs(us_length);
|
||||
|
||||
sspi_recv_token.cbBuffer = us_length;
|
||||
sspi_recv_token.pvBuffer = malloc(us_length);
|
||||
|
||||
if(!sspi_recv_token.pvBuffer) {
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
|
||||
sspi_recv_token.cbBuffer,
|
||||
&actualread, timeout);
|
||||
|
||||
if(result != CURLE_OK || actualread != us_length) {
|
||||
failf(data, "Failed to receive SSPI authentication token.");
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
context_handle = &sspi_context;
|
||||
}
|
||||
|
||||
free(service_name);
|
||||
service_name=NULL;
|
||||
|
||||
/* Everything is good so far, user was authenticated! */
|
||||
sspi_major_status = s_pSecFn->QueryCredentialsAttributes( &cred_handle,
|
||||
SECPKG_CRED_ATTR_NAMES,
|
||||
&names);
|
||||
s_pSecFn->FreeCredentialsHandle(&cred_handle);
|
||||
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
|
||||
"QueryCredentialAttributes") ){
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
s_pSecFn->FreeContextBuffer(names.sUserName);
|
||||
failf(data, "Failed to determine user name.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
infof(data, "SOCKS5 server authencticated user %s with gssapi.\n",
|
||||
names.sUserName);
|
||||
s_pSecFn->FreeContextBuffer(names.sUserName);
|
||||
|
||||
/* Do encryption */
|
||||
socksreq[0] = 1; /* gssapi subnegotiation version */
|
||||
socksreq[1] = 2; /* encryption message type */
|
||||
|
||||
gss_enc = 0; /* no data protection */
|
||||
/* do confidentiality protection if supported */
|
||||
if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
|
||||
gss_enc = 2;
|
||||
/* else do integrity protection */
|
||||
else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
|
||||
gss_enc = 1;
|
||||
|
||||
infof(data, "SOCKS5 server supports gssapi %s data protection.\n",
|
||||
(gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
|
||||
/* force to no data protection, avoid encryption/decryption for now */
|
||||
gss_enc = 0;
|
||||
/*
|
||||
* Sending the encryption type in clear seems wrong. It should be
|
||||
* protected with gss_seal()/gss_wrap(). See RFC1961 extract below
|
||||
* The NEC reference implementations on which this is based is
|
||||
* therefore at fault
|
||||
*
|
||||
* +------+------+------+.......................+
|
||||
* + ver | mtyp | len | token |
|
||||
* +------+------+------+.......................+
|
||||
* + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
|
||||
* +------+------+------+.......................+
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* - "ver" is the protocol version number, here 1 to represent the
|
||||
* first version of the SOCKS/GSS-API protocol
|
||||
*
|
||||
* - "mtyp" is the message type, here 2 to represent a protection
|
||||
* -level negotiation message
|
||||
*
|
||||
* - "len" is the length of the "token" field in octets
|
||||
*
|
||||
* - "token" is the GSS-API encapsulated protection level
|
||||
*
|
||||
* The token is produced by encapsulating an octet containing the
|
||||
* required protection level using gss_seal()/gss_wrap() with conf_req
|
||||
* set to FALSE. The token is verified using gss_unseal()/
|
||||
* gss_unwrap().
|
||||
*
|
||||
*/
|
||||
|
||||
if(data->set.socks5_gssapi_nec) {
|
||||
us_length = htons((short)1);
|
||||
memcpy(socksreq+2, &us_length, sizeof(short));
|
||||
}
|
||||
else {
|
||||
sspi_major_status = s_pSecFn->QueryContextAttributesA( &sspi_context,
|
||||
SECPKG_ATTR_SIZES,
|
||||
&sspi_sizes);
|
||||
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
|
||||
"QueryContextAttributesA")) {
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
failf(data, "Failed to query security context attributes.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
|
||||
sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
|
||||
sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
|
||||
|
||||
if(!sspi_w_token[0].pvBuffer) {
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
sspi_w_token[1].cbBuffer = 1;
|
||||
sspi_w_token[1].pvBuffer = malloc(1);
|
||||
if(!sspi_w_token[1].pvBuffer){
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(sspi_w_token[1].pvBuffer,&gss_enc,1);
|
||||
sspi_w_token[2].BufferType = SECBUFFER_PADDING;
|
||||
sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
|
||||
sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
|
||||
if(!sspi_w_token[2].pvBuffer) {
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
sspi_major_status = s_pSecFn->EncryptMessage( &sspi_context,
|
||||
KERB_WRAP_NO_ENCRYPT,
|
||||
&wrap_desc,
|
||||
0);
|
||||
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
|
||||
"EncryptMessage") ) {
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
failf(data, "Failed to query security context attributes.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
|
||||
+ sspi_w_token[1].cbBuffer
|
||||
+ sspi_w_token[2].cbBuffer;
|
||||
sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer);
|
||||
if(!sspi_send_token.pvBuffer) {
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
|
||||
sspi_w_token[0].cbBuffer);
|
||||
memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
|
||||
sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
|
||||
memcpy((PUCHAR) sspi_send_token.pvBuffer
|
||||
+sspi_w_token[0].cbBuffer
|
||||
+sspi_w_token[1].cbBuffer,
|
||||
sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
|
||||
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
sspi_w_token[0].pvBuffer = NULL;
|
||||
sspi_w_token[0].cbBuffer = 0;
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
sspi_w_token[1].pvBuffer = NULL;
|
||||
sspi_w_token[1].cbBuffer = 0;
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
|
||||
sspi_w_token[2].pvBuffer = NULL;
|
||||
sspi_w_token[2].cbBuffer = 0;
|
||||
|
||||
us_length = htons((short)sspi_send_token.cbBuffer);
|
||||
memcpy(socksreq+2,&us_length,sizeof(short));
|
||||
}
|
||||
|
||||
code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
|
||||
if((code != CURLE_OK) || (4 != written)) {
|
||||
failf(data, "Failed to send SSPI encryption request.");
|
||||
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(data->set.socks5_gssapi_nec) {
|
||||
memcpy(socksreq,&gss_enc,1);
|
||||
code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
|
||||
if((code != CURLE_OK) || (1 != written)) {
|
||||
failf(data, "Failed to send SSPI encryption type.");
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
} else {
|
||||
code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
|
||||
sspi_send_token.cbBuffer, &written);
|
||||
if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) {
|
||||
failf(data, "Failed to send SSPI encryption type.");
|
||||
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
|
||||
}
|
||||
|
||||
result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
|
||||
&actualread, timeout);
|
||||
if(result != CURLE_OK || actualread != 4) {
|
||||
failf(data, "Failed to receive SSPI encryption response.");
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
/* ignore the first (VER) byte */
|
||||
if(socksreq[1] == 255) { /* status / message type */
|
||||
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(socksreq[1] != 2) { /* status / message type */
|
||||
failf(data, "Invalid SSPI encryption response type (%d %d).",
|
||||
socksreq[0], socksreq[1]);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(&us_length, socksreq+2, sizeof(short));
|
||||
us_length = ntohs(us_length);
|
||||
|
||||
sspi_w_token[0].cbBuffer = us_length;
|
||||
sspi_w_token[0].pvBuffer = malloc(us_length);
|
||||
if(!sspi_w_token[0].pvBuffer) {
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result=Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
|
||||
sspi_w_token[0].cbBuffer,
|
||||
&actualread, timeout);
|
||||
|
||||
if(result != CURLE_OK || actualread != us_length) {
|
||||
failf(data, "Failed to receive SSPI encryption type.");
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
|
||||
if(!data->set.socks5_gssapi_nec) {
|
||||
wrap_desc.cBuffers = 2;
|
||||
sspi_w_token[0].BufferType = SECBUFFER_STREAM;
|
||||
sspi_w_token[1].BufferType = SECBUFFER_DATA;
|
||||
sspi_w_token[1].cbBuffer = 0;
|
||||
sspi_w_token[1].pvBuffer = NULL;
|
||||
|
||||
sspi_major_status = s_pSecFn->DecryptMessage( &sspi_context,
|
||||
&wrap_desc,
|
||||
0,
|
||||
&qop);
|
||||
|
||||
if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
|
||||
"DecryptMessage")) {
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
failf(data, "Failed to query security context attributes.");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
if(sspi_w_token[1].cbBuffer != 1) {
|
||||
failf(data, "Invalid SSPI encryption response length (%d).",
|
||||
sspi_w_token[1].cbBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
|
||||
memcpy(socksreq,sspi_w_token[1].pvBuffer,sspi_w_token[1].cbBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
|
||||
} else {
|
||||
if(sspi_w_token[0].cbBuffer != 1) {
|
||||
failf(data, "Invalid SSPI encryption response length (%d).",
|
||||
sspi_w_token[0].cbBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
memcpy(socksreq,sspi_w_token[0].pvBuffer,sspi_w_token[0].cbBuffer);
|
||||
s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
|
||||
}
|
||||
|
||||
infof(data, "SOCKS5 access with%s protection granted.\n",
|
||||
(socksreq[0]==0)?"out gssapi data":
|
||||
((socksreq[0]==1)?" gssapi integrity":" gssapi confidentiality"));
|
||||
|
||||
/* For later use if encryption is required
|
||||
conn->socks5_gssapi_enctype = socksreq[0];
|
||||
if (socksreq[0] != 0)
|
||||
conn->socks5_sspi_context = sspi_context;
|
||||
else {
|
||||
s_pSecFn->DeleteSecurityContext(&sspi_context);
|
||||
conn->socks5_sspi_context = sspi_context;
|
||||
}
|
||||
*/
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -21,9 +21,9 @@
|
||||
* $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 'gtls' function in gtls.c (GnuTLS based).
|
||||
/* This file is for implementing all "generic" SSL functions that all libcurl
|
||||
internals should use. It is then responsible for calling the proper
|
||||
"backend" function.
|
||||
|
||||
SSL-functions in libcurl should call functions in this source file, and not
|
||||
to any specific SSL-layer.
|
||||
|
26
lib/ssluse.c
26
lib/ssluse.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -994,7 +994,7 @@ static int hostmatch(const char *hostname, const char *pattern)
|
||||
break;
|
||||
}
|
||||
|
||||
if(toupper(c) != toupper(*hostname++))
|
||||
if(Curl_raw_toupper(c) != Curl_raw_toupper(*hostname++))
|
||||
break;
|
||||
}
|
||||
return HOST_NOMATCH;
|
||||
@@ -1385,8 +1385,28 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
enable the bug workaround options if compatibility with somewhat broken
|
||||
implementations is desired."
|
||||
|
||||
The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
|
||||
disable "rfc4507bis session ticket support". rfc4507bis was later turned
|
||||
into the proper RFC5077 it seems: http://tools.ietf.org/html/rfc5077
|
||||
|
||||
The enabled extension concerns the session management. I wonder how often
|
||||
libcurl stops a connection and then resumes a TLS session. also, sending
|
||||
the session data is some overhead. .I suggest that you just use your
|
||||
proposed patch (which explicitly disables TICKET).
|
||||
|
||||
If someone writes an application with libcurl and openssl who wants to
|
||||
enable the feature, one can do this in the SSL callback.
|
||||
|
||||
*/
|
||||
SSL_CTX_set_options(connssl->ctx, SSL_OP_ALL);
|
||||
#ifdef SSL_OP_NO_TICKET
|
||||
/* expect older openssl releases to not have this define so only use it if
|
||||
present */
|
||||
#define CURL_CTX_OPTIONS SSL_OP_ALL|SSL_OP_NO_TICKET
|
||||
#else
|
||||
#define CURL_CTX_OPTIONS SSL_OP_ALL
|
||||
#endif
|
||||
|
||||
SSL_CTX_set_options(connssl->ctx, CURL_CTX_OPTIONS);
|
||||
|
||||
/* disable SSLv2 in the default case (i.e. allow SSLv3 and TLSv1) */
|
||||
if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT)
|
||||
|
44
lib/telnet.c
44
lib/telnet.c
@@ -1124,7 +1124,7 @@ void telrcv(struct connectdata *conn,
|
||||
/* Escape and send a telnet data block */
|
||||
/* TODO: write large chunks of data instead of one byte at a time */
|
||||
static CURLcode send_telnet_data(struct connectdata *conn,
|
||||
char *buffer, ssize_t nread)
|
||||
char *buffer, ssize_t nread)
|
||||
{
|
||||
unsigned char outbuf[2];
|
||||
ssize_t bytes_written, total_written;
|
||||
@@ -1144,16 +1144,16 @@ static CURLcode send_telnet_data(struct connectdata *conn,
|
||||
pfd[0].fd = conn->sock[FIRSTSOCKET];
|
||||
pfd[0].events = POLLOUT;
|
||||
switch (Curl_poll(pfd, 1, -1)) {
|
||||
case -1: /* error, abort writing */
|
||||
case 0: /* timeout (will never happen) */
|
||||
rc = CURLE_SEND_ERROR;
|
||||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written,
|
||||
out_count-total_written, &bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
case -1: /* error, abort writing */
|
||||
case 0: /* timeout (will never happen) */
|
||||
rc = CURLE_SEND_ERROR;
|
||||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written,
|
||||
out_count-total_written, &bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
}
|
||||
/* handle partial write */
|
||||
} while (rc == CURLE_OK && total_written < out_count);
|
||||
@@ -1317,7 +1317,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
while(1) {
|
||||
if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
|
||||
keepon = FALSE;
|
||||
code = CURLE_READ_ERROR;
|
||||
code = CURLE_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1327,15 +1327,15 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
|
||||
&readfile_read, NULL)) {
|
||||
keepon = FALSE;
|
||||
code = CURLE_READ_ERROR;
|
||||
code = CURLE_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
code = send_telnet_data(conn, buf, readfile_read);
|
||||
if(code) {
|
||||
if(code) {
|
||||
keepon = FALSE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1345,14 +1345,14 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
|
||||
&readfile_read, NULL)) {
|
||||
keepon = FALSE;
|
||||
code = CURLE_READ_ERROR;
|
||||
code = CURLE_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
code = send_telnet_data(conn, buf, readfile_read);
|
||||
if(code) {
|
||||
keepon = FALSE;
|
||||
break;
|
||||
keepon = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1417,10 +1417,10 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
|
||||
if(pfd[1].revents & POLLIN) { /* read from stdin */
|
||||
nread = read(0, buf, 255);
|
||||
code = send_telnet_data(conn, buf, nread);
|
||||
if(code) {
|
||||
if(code) {
|
||||
keepon = FALSE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(pfd[0].revents & POLLIN) {
|
||||
|
334
lib/tftp.c
334
lib/tftp.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -26,7 +26,6 @@
|
||||
#ifndef CURL_DISABLE_TFTP
|
||||
/* -- WIN32 approved -- */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
@@ -72,6 +71,7 @@
|
||||
#include "strerror.h"
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "url.h"
|
||||
#include "rawstr.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -82,8 +82,13 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* RFC2348 allows the block size to be negotiated, but we don't support that */
|
||||
#define TFTP_BLOCKSIZE 512
|
||||
/* RFC2348 allows the block size to be negotiated */
|
||||
#define TFTP_BLKSIZE_DEFAULT 512
|
||||
#define TFTP_BLKSIZE_MIN 8
|
||||
#define TFTP_BLKSIZE_MAX 65464
|
||||
#define TFTP_OPTION_BLKSIZE "blksize"
|
||||
#define TFTP_OPTION_TSIZE "tsize"
|
||||
#define TFTP_OPTION_INTERVAL "interval"
|
||||
|
||||
typedef enum {
|
||||
TFTP_MODE_NETASCII=0,
|
||||
@@ -104,6 +109,7 @@ typedef enum {
|
||||
TFTP_EVENT_DATA = 3,
|
||||
TFTP_EVENT_ACK = 4,
|
||||
TFTP_EVENT_ERROR = 5,
|
||||
TFTP_EVENT_OACK = 6,
|
||||
TFTP_EVENT_TIMEOUT
|
||||
} tftp_event_t;
|
||||
|
||||
@@ -124,7 +130,7 @@ typedef enum {
|
||||
} tftp_error_t;
|
||||
|
||||
typedef struct tftp_packet {
|
||||
unsigned char data[2 + 2 + TFTP_BLOCKSIZE];
|
||||
unsigned char *data;
|
||||
} tftp_packet_t;
|
||||
|
||||
typedef struct tftp_state_data {
|
||||
@@ -134,8 +140,8 @@ typedef struct tftp_state_data {
|
||||
struct connectdata *conn;
|
||||
curl_socket_t sockfd;
|
||||
int retries;
|
||||
int retry_time;
|
||||
int retry_max;
|
||||
time_t retry_time;
|
||||
time_t retry_max;
|
||||
time_t start_time;
|
||||
time_t max_time;
|
||||
unsigned short block;
|
||||
@@ -143,7 +149,9 @@ typedef struct tftp_state_data {
|
||||
struct Curl_sockaddr_storage remote_addr;
|
||||
socklen_t remote_addrlen;
|
||||
ssize_t rbytes;
|
||||
int sbytes;
|
||||
size_t sbytes;
|
||||
size_t blksize;
|
||||
int requested_blksize;
|
||||
tftp_packet_t rpacket;
|
||||
tftp_packet_t spacket;
|
||||
} tftp_state_data_t;
|
||||
@@ -153,6 +161,7 @@ typedef struct tftp_state_data {
|
||||
static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
|
||||
static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
|
||||
static CURLcode tftp_connect(struct connectdata *conn, bool *done);
|
||||
static CURLcode tftp_disconnect(struct connectdata *conn);
|
||||
static CURLcode tftp_do(struct connectdata *conn, bool *done);
|
||||
static CURLcode tftp_done(struct connectdata *conn,
|
||||
CURLcode, bool premature);
|
||||
@@ -175,7 +184,7 @@ const struct Curl_handler Curl_handler_tftp = {
|
||||
ZERO_NULL, /* proto_getsock */
|
||||
ZERO_NULL, /* doing_getsock */
|
||||
ZERO_NULL, /* perform_getsock */
|
||||
ZERO_NULL, /* disconnect */
|
||||
tftp_disconnect, /* disconnect */
|
||||
PORT_TFTP, /* defport */
|
||||
PROT_TFTP /* protocol */
|
||||
};
|
||||
@@ -195,7 +204,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
|
||||
{
|
||||
time_t maxtime, timeout;
|
||||
long timeout_ms;
|
||||
const bool start = (state->state == TFTP_STATE_START);
|
||||
bool start = (bool)(state->state == TFTP_STATE_START);
|
||||
|
||||
time(&state->start_time);
|
||||
|
||||
@@ -256,7 +265,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
|
||||
state->retry_time=1;
|
||||
|
||||
infof(state->conn->data,
|
||||
"set timeouts for state %d; Total %d, retry %d maxtry %d\n",
|
||||
"set timeouts for state %d; Total %d, retry %d maxtry %d\n",
|
||||
state->state, (state->max_time-state->start_time),
|
||||
state->retry_time, state->retry_max);
|
||||
|
||||
@@ -294,11 +303,143 @@ static unsigned short getrpacketblock(const tftp_packet_t *packet)
|
||||
return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
|
||||
}
|
||||
|
||||
static size_t Curl_strnlen(const char *string, size_t maxlen)
|
||||
{
|
||||
const char *end = memchr (string, '\0', maxlen);
|
||||
return end ? (size_t) (end - string) : maxlen;
|
||||
}
|
||||
|
||||
static const char *tftp_option_get(const char *buf, size_t len,
|
||||
const char **option, const char **value)
|
||||
{
|
||||
size_t loc;
|
||||
|
||||
loc = Curl_strnlen( buf, len );
|
||||
loc++; /* NULL term */
|
||||
|
||||
if (loc >= len)
|
||||
return NULL;
|
||||
*option = buf;
|
||||
|
||||
loc += Curl_strnlen( buf+loc, len-loc );
|
||||
loc++; /* NULL term */
|
||||
|
||||
if (loc > len)
|
||||
return NULL;
|
||||
*value = &buf[strlen(*option) + 1];
|
||||
|
||||
return &buf[loc];
|
||||
}
|
||||
|
||||
static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
|
||||
const char *ptr, int len)
|
||||
{
|
||||
const char *tmp = ptr;
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
|
||||
/* if OACK doesn't contain blksize option, the default (512) must be used */
|
||||
state->blksize = TFTP_BLKSIZE_DEFAULT;
|
||||
|
||||
while (tmp < ptr + len) {
|
||||
const char *option, *value;
|
||||
|
||||
tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
|
||||
if(tmp == NULL) {
|
||||
failf(data, "Malformed ACK packet, rejecting");
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
|
||||
infof(data, "got option=(%s) value=(%s)\n", option, value);
|
||||
|
||||
if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
|
||||
int blksize;
|
||||
|
||||
blksize = strtol( value, NULL, 10 );
|
||||
|
||||
if(!blksize) {
|
||||
failf(data, "invalid blocksize value in OACK packet");
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
else if(blksize > TFTP_BLKSIZE_MAX) {
|
||||
failf(data, "%s (%d)", "blksize is larger than max supported",
|
||||
TFTP_BLKSIZE_MAX);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
else if(blksize < TFTP_BLKSIZE_MIN) {
|
||||
failf(data, "%s (%d)", "blksize is smaller than min supported",
|
||||
TFTP_BLKSIZE_MIN);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
else if (blksize > state->requested_blksize) {
|
||||
/* could realloc pkt buffers here, but the spec doesn't call out
|
||||
* support for the server requesting a bigger blksize than the client
|
||||
* requests */
|
||||
failf(data, "%s (%d)",
|
||||
"server requested blksize larger than allocated", blksize);
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
|
||||
state->blksize = blksize;
|
||||
infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK",
|
||||
state->blksize, "requested", state->requested_blksize);
|
||||
}
|
||||
else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
|
||||
long tsize = 0;
|
||||
|
||||
tsize = strtol( value, NULL, 10 );
|
||||
if(!tsize) {
|
||||
failf(data, "invalid tsize value in OACK packet");
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
Curl_pgrsSetDownloadSize(data, tsize);
|
||||
infof(data, "%s (%d)\n", "tsize parsed from OACK", tsize);
|
||||
}
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
|
||||
char *buf, const char *option)
|
||||
{
|
||||
if( ( strlen(option) + csize + 1U ) > state->blksize )
|
||||
return 0;
|
||||
strcpy(buf, option);
|
||||
return( strlen(option) + 1 );
|
||||
}
|
||||
|
||||
static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
{
|
||||
CURLcode res;
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
|
||||
infof(data, "%s\n", "Connected for transmit");
|
||||
state->state = TFTP_STATE_TX;
|
||||
res = tftp_set_timeouts(state);
|
||||
if(res != CURLE_OK)
|
||||
return(res);
|
||||
return tftp_tx(state, event);
|
||||
}
|
||||
|
||||
static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
{
|
||||
CURLcode res;
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
|
||||
infof(data, "%s\n", "Connected for receive");
|
||||
state->state = TFTP_STATE_RX;
|
||||
res = tftp_set_timeouts(state);
|
||||
if(res != CURLE_OK)
|
||||
return(res);
|
||||
return tftp_rx(state, event);
|
||||
}
|
||||
|
||||
static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
{
|
||||
int sbytes;
|
||||
const char *mode = "octet";
|
||||
char *filename;
|
||||
char buf[8];
|
||||
struct SessionHandle *data = state->conn->data;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
@@ -322,7 +463,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
/* If we are uploading, send an WRQ */
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
|
||||
state->conn->data->req.upload_fromhere =
|
||||
(char *)&state->spacket.data[4];
|
||||
(char *)state->spacket.data+4;
|
||||
if(data->set.infilesize != -1)
|
||||
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||
}
|
||||
@@ -331,17 +472,40 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
|
||||
}
|
||||
/* As RFC3617 describes the separator slash is not actually part of the
|
||||
file name so we skip the always-present first letter of the path string. */
|
||||
file name so we skip the always-present first letter of the path
|
||||
string. */
|
||||
filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
|
||||
NULL);
|
||||
if(!filename)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
snprintf((char *)&state->spacket.data[2],
|
||||
TFTP_BLOCKSIZE,
|
||||
snprintf((char *)state->spacket.data+2,
|
||||
state->blksize,
|
||||
"%s%c%s%c", filename, '\0', mode, '\0');
|
||||
sbytes = 4 + (int)strlen(filename) + (int)strlen(mode);
|
||||
sbytes = sendto(state->sockfd, (void *)&state->spacket,
|
||||
sbytes = 4 + strlen(filename) + strlen(mode);
|
||||
|
||||
/* add tsize option */
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_TSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, "0");
|
||||
/* add blksize option */
|
||||
snprintf( buf, sizeof(buf), "%d", state->requested_blksize );
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_BLKSIZE);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
/* add timeout option */
|
||||
snprintf( buf, sizeof(buf), "%d", state->retry_time );
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes,
|
||||
TFTP_OPTION_INTERVAL);
|
||||
sbytes += tftp_option_add(state, sbytes,
|
||||
(char *)state->spacket.data+sbytes, buf );
|
||||
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
sbytes, 0,
|
||||
state->conn->ip_addr->ai_addr,
|
||||
state->conn->ip_addr->ai_addrlen);
|
||||
@@ -351,21 +515,22 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||
Curl_safefree(filename);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_ACK: /* Connected for transmit */
|
||||
infof(data, "%s\n", "Connected for transmit");
|
||||
state->state = TFTP_STATE_TX;
|
||||
res = tftp_set_timeouts(state);
|
||||
if(res)
|
||||
break;
|
||||
return tftp_tx(state, event);
|
||||
case TFTP_EVENT_OACK:
|
||||
if(data->set.upload) {
|
||||
res = tftp_connect_for_tx(state, event);
|
||||
}
|
||||
else {
|
||||
res = tftp_connect_for_rx(state, event);
|
||||
}
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_DATA: /* connected for receive */
|
||||
infof(data, "%s\n", "Connected for receive");
|
||||
state->state = TFTP_STATE_RX;
|
||||
res = tftp_set_timeouts(state);
|
||||
if(res)
|
||||
break;
|
||||
return tftp_rx(state, event);
|
||||
case TFTP_EVENT_ACK: /* Connected for transmit */
|
||||
res = tftp_connect_for_tx(state, event);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_DATA: /* Connected for receive */
|
||||
res = tftp_connect_for_rx(state, event);
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_ERROR:
|
||||
state->state = TFTP_STATE_FIN;
|
||||
@@ -394,7 +559,6 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
switch(event) {
|
||||
|
||||
case TFTP_EVENT_DATA:
|
||||
|
||||
/* Is this the block we expect? */
|
||||
rblock = getrpacketblock(&state->rpacket);
|
||||
if((state->block+1) != rblock) {
|
||||
@@ -423,7 +587,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
}
|
||||
|
||||
/* Check if completed (That is, a less than full packet is received) */
|
||||
if(state->rbytes < (ssize_t)sizeof(state->spacket)){
|
||||
if(state->rbytes < (ssize_t)state->blksize+4){
|
||||
state->state = TFTP_STATE_FIN;
|
||||
}
|
||||
else {
|
||||
@@ -431,6 +595,25 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
}
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_OACK:
|
||||
/* ACK option acknowledgement so we can move on to data */
|
||||
state->block = 0;
|
||||
state->retries = 0;
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_ACK);
|
||||
setpacketblock(&state->spacket, state->block);
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
4, SEND_4TH_ARG,
|
||||
(struct sockaddr *)&state->remote_addr,
|
||||
state->remote_addrlen);
|
||||
if(sbytes < 0) {
|
||||
failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
|
||||
return CURLE_SEND_ERROR;
|
||||
}
|
||||
|
||||
/* we're ready to RX data */
|
||||
state->state = TFTP_STATE_RX;
|
||||
break;
|
||||
|
||||
case TFTP_EVENT_TIMEOUT:
|
||||
/* Increment the retry count and fail if over the limit */
|
||||
state->retries++;
|
||||
@@ -442,7 +625,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||
}
|
||||
else {
|
||||
/* Resend the previous ACK */
|
||||
sbytes = sendto(state->sockfd, (void *)&state->spacket,
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
4, SEND_4TH_ARG,
|
||||
(struct sockaddr *)&state->remote_addr,
|
||||
state->remote_addrlen);
|
||||
@@ -518,11 +701,12 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
state->retries = 0;
|
||||
setpacketevent(&state->spacket, TFTP_EVENT_DATA);
|
||||
setpacketblock(&state->spacket, state->block);
|
||||
if(state->block > 1 && state->sbytes < TFTP_BLOCKSIZE) {
|
||||
if(state->block > 1 && state->sbytes < state->blksize) {
|
||||
state->state = TFTP_STATE_FIN;
|
||||
return CURLE_OK;
|
||||
}
|
||||
res = Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes);
|
||||
res = Curl_fillreadbuffer(state->conn, state->blksize,
|
||||
(int *)&state->sbytes);
|
||||
if(res)
|
||||
return res;
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
@@ -551,7 +735,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||
}
|
||||
else {
|
||||
/* Re-send the data packet */
|
||||
sbytes = sendto(state->sockfd, (void *)&state->spacket,
|
||||
sbytes = sendto(state->sockfd, (void *)state->spacket.data,
|
||||
4+state->sbytes, SEND_4TH_ARG,
|
||||
(struct sockaddr *)&state->remote_addr,
|
||||
state->remote_addrlen);
|
||||
@@ -614,6 +798,26 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
|
||||
return res;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* tftp_disconnect
|
||||
*
|
||||
* The disconnect callback
|
||||
*
|
||||
**********************************************************/
|
||||
static CURLcode tftp_disconnect(struct connectdata *conn)
|
||||
{
|
||||
tftp_state_data_t *state = conn->proto.tftpc;
|
||||
|
||||
/* done, free dynamically allocated pkt buffers */
|
||||
if(state) {
|
||||
Curl_safefree(state->rpacket.data);
|
||||
Curl_safefree(state->spacket.data);
|
||||
free(state);
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
@@ -626,17 +830,36 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
CURLcode code;
|
||||
tftp_state_data_t *state;
|
||||
int rc;
|
||||
int blksize, rc;
|
||||
|
||||
blksize = TFTP_BLKSIZE_DEFAULT;
|
||||
|
||||
/* If there already is a protocol-specific struct allocated for this
|
||||
sessionhandle, deal with it */
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
state = conn->data->state.proto.tftp;
|
||||
if(!state) {
|
||||
state = conn->data->state.proto.tftp = calloc(sizeof(tftp_state_data_t),
|
||||
1);
|
||||
if(!state)
|
||||
state = conn->proto.tftpc = calloc(sizeof(tftp_state_data_t), 1);
|
||||
if(!state)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* alloc pkt buffers based on specified blksize */
|
||||
if(conn->data->set.tftp_blksize) {
|
||||
blksize = conn->data->set.tftp_blksize;
|
||||
if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN )
|
||||
return CURLE_TFTP_ILLEGAL;
|
||||
}
|
||||
|
||||
if(!state->rpacket.data) {
|
||||
state->rpacket.data = calloc(1, blksize + 2 + 2);
|
||||
|
||||
if(!state->rpacket.data)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(!state->spacket.data) {
|
||||
state->spacket.data = calloc(1, blksize + 2 + 2);
|
||||
|
||||
if(!state->spacket.data)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -646,6 +869,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
|
||||
state->sockfd = state->conn->sock[FIRSTSOCKET];
|
||||
state->state = TFTP_STATE_START;
|
||||
state->error = TFTP_ERR_NONE;
|
||||
state->blksize = TFTP_BLKSIZE_DEFAULT;
|
||||
state->requested_blksize = blksize;
|
||||
|
||||
((struct sockaddr *)&state->local_addr)->sa_family =
|
||||
(unsigned short)(conn->ip_addr->ai_family);
|
||||
@@ -734,12 +959,12 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
*/
|
||||
Curl_reset_reqproto(conn);
|
||||
|
||||
if(!data->state.proto.tftp) {
|
||||
if(!conn->proto.tftpc) {
|
||||
code = tftp_connect(conn, done);
|
||||
if(code)
|
||||
return code;
|
||||
}
|
||||
state = (tftp_state_data_t *)data->state.proto.tftp;
|
||||
state = (tftp_state_data_t *)conn->proto.tftpc;
|
||||
|
||||
/* Run the TFTP State Machine */
|
||||
for(code=tftp_state_machine(state, TFTP_EVENT_INIT);
|
||||
@@ -748,7 +973,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
|
||||
/* Wait until ready to read or timeout occurs */
|
||||
rc=Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD,
|
||||
state->retry_time * 1000);
|
||||
(int)(state->retry_time * 1000));
|
||||
|
||||
if(rc == -1) {
|
||||
/* bail out */
|
||||
@@ -769,8 +994,8 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
/* Receive the packet */
|
||||
fromlen = sizeof(fromaddr);
|
||||
state->rbytes = (ssize_t)recvfrom(state->sockfd,
|
||||
(void *)&state->rpacket,
|
||||
sizeof(state->rpacket),
|
||||
(void *)state->rpacket.data,
|
||||
state->blksize+4,
|
||||
0,
|
||||
(struct sockaddr *)&fromaddr,
|
||||
&fromlen);
|
||||
@@ -796,7 +1021,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
if(state->rbytes > 4 &&
|
||||
((state->block+1) == getrpacketblock(&state->rpacket))) {
|
||||
code = Curl_client_write(conn, CLIENTWRITE_BODY,
|
||||
(char *)&state->rpacket.data[4],
|
||||
(char *)state->rpacket.data+4,
|
||||
state->rbytes-4);
|
||||
if(code)
|
||||
return code;
|
||||
@@ -806,10 +1031,17 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
|
||||
break;
|
||||
case TFTP_EVENT_ERROR:
|
||||
state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
|
||||
infof(data, "%s\n", (const char *)&state->rpacket.data[4]);
|
||||
infof(data, "%s\n", (const char *)state->rpacket.data+4);
|
||||
break;
|
||||
case TFTP_EVENT_ACK:
|
||||
break;
|
||||
case TFTP_EVENT_OACK:
|
||||
code = tftp_parse_option_ack(state,
|
||||
(const char *)state->rpacket.data+2,
|
||||
state->rbytes-2);
|
||||
if(code)
|
||||
return code;
|
||||
break;
|
||||
case TFTP_EVENT_RRQ:
|
||||
case TFTP_EVENT_WRQ:
|
||||
default:
|
||||
@@ -904,7 +1136,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
|
||||
|
||||
if(type) {
|
||||
*type = 0; /* it was in the middle of the hostname */
|
||||
command = (char) toupper((int) type[6]);
|
||||
command = Curl_raw_toupper(type[6]);
|
||||
|
||||
switch (command) {
|
||||
case 'A': /* ASCII mode */
|
||||
|
1205
lib/transfer.c
1205
lib/transfer.c
File diff suppressed because it is too large
Load Diff
338
lib/url.c
338
lib/url.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -683,6 +683,26 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
|
||||
set->new_file_perms = 0644; /* Default permissions */
|
||||
set->new_directory_perms = 0755; /* Default permissions */
|
||||
|
||||
/* for the *protocols fields we don't use the CURLPROTO_ALL convenience
|
||||
define since we internally only use the lower 16 bits for the passed
|
||||
in bitmask to not conflict with the private bits */
|
||||
set->allowed_protocols = PROT_EXTMASK;
|
||||
set->redir_protocols =
|
||||
PROT_EXTMASK & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
/*
|
||||
* disallow unprotected protection negotiation NEC reference implementation
|
||||
* seem not to follow rfc1961 section 4.3/4.4
|
||||
*/
|
||||
set->socks5_gssapi_nec = FALSE;
|
||||
/* set default gssapi service name */
|
||||
res = setstropt(&set->str[STRING_SOCKS5_GSSAPI_SERVICE],
|
||||
(char *) CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE);
|
||||
if (res != CURLE_OK)
|
||||
return res;
|
||||
#endif
|
||||
|
||||
/* This is our preferred CA cert bundle/path since install time */
|
||||
#if defined(CURL_CA_BUNDLE)
|
||||
res = setstropt(&set->str[STRING_SSL_CAFILE], (char *) CURL_CA_BUNDLE);
|
||||
@@ -908,7 +928,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
* An FTP option that modifies an upload to create missing directories on
|
||||
* the server.
|
||||
*/
|
||||
data->set.ftp_create_missing_dirs = (bool)(0 != va_arg(param, long));
|
||||
data->set.ftp_create_missing_dirs = (int)va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_FTP_RESPONSE_TIMEOUT:
|
||||
/*
|
||||
@@ -917,6 +937,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
*/
|
||||
data->set.ftp_response_timeout = va_arg( param , long ) * 1000;
|
||||
break;
|
||||
case CURLOPT_TFTP_BLKSIZE:
|
||||
/*
|
||||
* TFTP option that specifies the block size to use for data transmission
|
||||
*/
|
||||
data->set.tftp_blksize = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_DIRLISTONLY:
|
||||
/*
|
||||
* An option that changes the command to one that asks for a list
|
||||
@@ -1336,7 +1362,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
|
||||
/* the DIGEST_IE bit is only used to set a special marker, for all the
|
||||
rest we need to handle it as normal DIGEST */
|
||||
data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
|
||||
data->state.authhost.iestyle = (bool)((auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE);
|
||||
|
||||
if(auth & CURLAUTH_DIGEST_IE) {
|
||||
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
|
||||
@@ -1381,7 +1407,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
|
||||
/* the DIGEST_IE bit is only used to set a special marker, for all the
|
||||
rest we need to handle it as normal DIGEST */
|
||||
data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE;
|
||||
data->state.authproxy.iestyle = (bool)((auth & CURLAUTH_DIGEST_IE)?TRUE:FALSE);
|
||||
|
||||
if(auth & CURLAUTH_DIGEST_IE) {
|
||||
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
|
||||
@@ -1418,7 +1444,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
|
||||
case CURLOPT_PROXYTYPE:
|
||||
/*
|
||||
* Set proxy type. HTTP/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
|
||||
* Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
|
||||
*/
|
||||
data->set.proxytype = (curl_proxytype)va_arg(param, long);
|
||||
break;
|
||||
@@ -1442,6 +1468,23 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
|
||||
/*
|
||||
* Set gssapi service name
|
||||
*/
|
||||
result = setstropt(&data->set.str[STRING_SOCKS5_GSSAPI_SERVICE],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
|
||||
case CURLOPT_SOCKS5_GSSAPI_NEC:
|
||||
/*
|
||||
* set flag for nec socks5 support
|
||||
*/
|
||||
data->set.socks5_gssapi_nec = (bool)(0 != va_arg(param, long));
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CURLOPT_WRITEHEADER:
|
||||
/*
|
||||
* Custom pointer to pass the header write callback function
|
||||
@@ -1662,6 +1705,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
case CURLOPT_NOPROXY:
|
||||
/*
|
||||
* proxy exception list
|
||||
*/
|
||||
result = setstropt(&data->set.str[STRING_NOPROXY],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CURLOPT_RANGE:
|
||||
@@ -2173,6 +2223,22 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
data->set.scope = (unsigned int) va_arg(param, long);
|
||||
break;
|
||||
|
||||
case CURLOPT_PROTOCOLS:
|
||||
/* set the bitmask for the protocols that are allowed to be used for the
|
||||
transfer, which thus helps the app which takes URLs from users or other
|
||||
external inputs and want to restrict what protocol(s) to deal
|
||||
with. Defaults to CURLPROTO_ALL. */
|
||||
data->set.allowed_protocols = va_arg(param, long) & PROT_EXTMASK;
|
||||
break;
|
||||
|
||||
case CURLOPT_REDIR_PROTOCOLS:
|
||||
/* set the bitmask for the protocols that libcurl is allowed to follow to,
|
||||
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
|
||||
to be set in both bitmasks to be allowed to get redirected to. Defaults
|
||||
to all protocols except FILE and SCP. */
|
||||
data->set.redir_protocols = va_arg(param, long) & PROT_EXTMASK;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown tag and its companion, just ignore: */
|
||||
result = CURLE_FAILED_INIT; /* correct this */
|
||||
@@ -2421,11 +2487,11 @@ static struct SessionHandle* gethandleathead(struct curl_llist *pipeline)
|
||||
void Curl_getoff_all_pipelines(struct SessionHandle *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
bool recv_head = conn->readchannel_inuse &&
|
||||
(gethandleathead(conn->recv_pipe) == data);
|
||||
bool recv_head = (bool)(conn->readchannel_inuse &&
|
||||
(gethandleathead(conn->recv_pipe) == data));
|
||||
|
||||
bool send_head = conn->writechannel_inuse &&
|
||||
(gethandleathead(conn->send_pipe) == data);
|
||||
bool send_head = (bool)(conn->writechannel_inuse &&
|
||||
(gethandleathead(conn->send_pipe) == data));
|
||||
|
||||
if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
|
||||
conn->readchannel_inuse = FALSE;
|
||||
@@ -2798,6 +2864,7 @@ static CURLcode ConnectPlease(struct SessionHandle *data,
|
||||
break;
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
case CURLPROXY_HTTP:
|
||||
case CURLPROXY_HTTP_1_0:
|
||||
/* do nothing here. handled later. */
|
||||
break;
|
||||
default:
|
||||
@@ -3326,7 +3393,19 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,
|
||||
|
||||
for (pp = protocols; (p = *pp) != NULL; pp++)
|
||||
if(Curl_raw_equal(p->scheme, conn->protostr)) {
|
||||
/* Protocol found in table. Perform setup complement if some. */
|
||||
/* Protocol found in table. Check if allowed */
|
||||
if(!(data->set.allowed_protocols & p->protocol))
|
||||
/* nope, get out */
|
||||
break;
|
||||
|
||||
/* it is allowed for "normal" request, now do an extra check if this is
|
||||
the result of a redirect */
|
||||
if(data->state.this_is_a_follow &&
|
||||
!(data->set.redir_protocols & p->protocol))
|
||||
/* nope, get out */
|
||||
break;
|
||||
|
||||
/* Perform setup complement if some. */
|
||||
conn->handler = p;
|
||||
|
||||
if(p->setup_connection) {
|
||||
@@ -3353,6 +3432,80 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/****************************************************************
|
||||
* Checks if the host is in the noproxy list. returns true if it matches
|
||||
* and therefore the proxy should NOT be used.
|
||||
****************************************************************/
|
||||
static bool check_noproxy(const char* name, const char* no_proxy)
|
||||
{
|
||||
/* no_proxy=domain1.dom,host.domain2.dom
|
||||
* (a comma-separated list of hosts which should
|
||||
* not be proxied, or an asterisk to override
|
||||
* all proxy variables)
|
||||
*/
|
||||
size_t tok_start;
|
||||
size_t tok_end;
|
||||
const char* separator = ", ";
|
||||
size_t no_proxy_len;
|
||||
size_t namelen;
|
||||
char *endptr;
|
||||
|
||||
if(no_proxy && no_proxy[0]) {
|
||||
if(Curl_raw_equal("*", no_proxy)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* NO_PROXY was specified and it wasn't just an asterisk */
|
||||
|
||||
no_proxy_len = strlen(no_proxy);
|
||||
endptr = strchr(name, ':');
|
||||
if(endptr)
|
||||
namelen = endptr - name;
|
||||
else
|
||||
namelen = strlen(name);
|
||||
|
||||
tok_start = 0;
|
||||
for (tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
|
||||
while (tok_start < no_proxy_len &&
|
||||
strchr(separator, no_proxy[tok_start]) != NULL) {
|
||||
/* Look for the beginning of the token. */
|
||||
++tok_start;
|
||||
}
|
||||
|
||||
if(tok_start == no_proxy_len)
|
||||
break; /* It was all trailing separator chars, no more tokens. */
|
||||
|
||||
for (tok_end = tok_start; tok_end < no_proxy_len &&
|
||||
strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end) {
|
||||
/* Look for the end of the token. */
|
||||
}
|
||||
|
||||
/* To match previous behaviour, where it was necessary to specify
|
||||
* ".local.com" to prevent matching "notlocal.com", we will leave
|
||||
* the '.' off.
|
||||
*/
|
||||
if(no_proxy[tok_start] == '.')
|
||||
++tok_start;
|
||||
|
||||
if((tok_end - tok_start) <= namelen) {
|
||||
/* Match the last part of the name to the domain we are checking. */
|
||||
const char *checkn = name + namelen - (tok_end - tok_start);
|
||||
if(Curl_raw_nequal(no_proxy + tok_start, checkn, tok_end - tok_start)) {
|
||||
if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
|
||||
/* We either have an exact match, or the previous character is a .
|
||||
* so it is within the same domain, so no proxy for this host.
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
} /* if((tok_end - tok_start) <= namelen) */
|
||||
} /* for (tok_start = 0; tok_start < no_proxy_len;
|
||||
tok_start = tok_end + 1) */
|
||||
} /* NO_PROXY was specified and it wasn't just an asterisk */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Detect what (if any) proxy to use. Remember that this selects a host
|
||||
* name and is not limited to HTTP proxies only.
|
||||
@@ -3381,91 +3534,56 @@ static char *detect_proxy(struct connectdata *conn)
|
||||
* checked if the lowercase versions don't exist.
|
||||
*/
|
||||
char *no_proxy=NULL;
|
||||
char *no_proxy_tok_buf;
|
||||
char proxy_env[128];
|
||||
|
||||
no_proxy=curl_getenv("no_proxy");
|
||||
if(!no_proxy)
|
||||
no_proxy=curl_getenv("NO_PROXY");
|
||||
|
||||
if(!no_proxy || !Curl_raw_equal("*", no_proxy)) {
|
||||
/* NO_PROXY wasn't specified or it wasn't just an asterisk */
|
||||
char *nope;
|
||||
if(!check_noproxy(conn->host.name, no_proxy)) {
|
||||
/* It was not listed as without proxy */
|
||||
char *protop = conn->protostr;
|
||||
char *envp = proxy_env;
|
||||
char *prox;
|
||||
|
||||
nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL;
|
||||
while(nope) {
|
||||
size_t namelen;
|
||||
char *endptr = strchr(conn->host.name, ':');
|
||||
if(endptr)
|
||||
namelen=endptr-conn->host.name;
|
||||
else
|
||||
namelen=strlen(conn->host.name);
|
||||
/* Now, build <protocol>_proxy and check for such a one to use */
|
||||
while(*protop)
|
||||
*envp++ = (char)tolower((int)*protop++);
|
||||
|
||||
if(strlen(nope) <= namelen) {
|
||||
char *checkn=
|
||||
conn->host.name + namelen - strlen(nope);
|
||||
if(checkprefix(nope, checkn)) {
|
||||
/* no proxy for this host! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
nope=strtok_r(NULL, ", ", &no_proxy_tok_buf);
|
||||
}
|
||||
if(!nope) {
|
||||
/* It was not listed as without proxy */
|
||||
char *protop = conn->protostr;
|
||||
char *envp = proxy_env;
|
||||
char *prox;
|
||||
/* append _proxy */
|
||||
strcpy(envp, "_proxy");
|
||||
|
||||
/* Now, build <protocol>_proxy and check for such a one to use */
|
||||
while(*protop)
|
||||
*envp++ = (char)tolower((int)*protop++);
|
||||
/* read the protocol proxy: */
|
||||
prox=curl_getenv(proxy_env);
|
||||
|
||||
/* append _proxy */
|
||||
strcpy(envp, "_proxy");
|
||||
|
||||
/* read the protocol proxy: */
|
||||
/*
|
||||
* We don't try the uppercase version of HTTP_PROXY because of
|
||||
* security reasons:
|
||||
*
|
||||
* When curl is used in a webserver application
|
||||
* environment (cgi or php), this environment variable can
|
||||
* be controlled by the web server user by setting the
|
||||
* http header 'Proxy:' to some value.
|
||||
*
|
||||
* This can cause 'internal' http/ftp requests to be
|
||||
* arbitrarily redirected by any external attacker.
|
||||
*/
|
||||
if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
|
||||
/* There was no lowercase variable, try the uppercase version: */
|
||||
Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
|
||||
prox=curl_getenv(proxy_env);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't try the uppercase version of HTTP_PROXY because of
|
||||
* security reasons:
|
||||
*
|
||||
* When curl is used in a webserver application
|
||||
* environment (cgi or php), this environment variable can
|
||||
* be controlled by the web server user by setting the
|
||||
* http header 'Proxy:' to some value.
|
||||
*
|
||||
* This can cause 'internal' http/ftp requests to be
|
||||
* arbitrarily redirected by any external attacker.
|
||||
*/
|
||||
if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
|
||||
/* There was no lowercase variable, try the uppercase version: */
|
||||
for(envp = proxy_env; *envp; envp++)
|
||||
*envp = (char)toupper((int)*envp);
|
||||
prox=curl_getenv(proxy_env);
|
||||
}
|
||||
|
||||
if(prox && *prox) { /* don't count "" strings */
|
||||
proxy = prox; /* use this */
|
||||
}
|
||||
else {
|
||||
proxy = curl_getenv("all_proxy"); /* default proxy to use */
|
||||
if(!proxy)
|
||||
proxy=curl_getenv("ALL_PROXY");
|
||||
}
|
||||
|
||||
if(proxy && *proxy) {
|
||||
long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
|
||||
|
||||
if(conn->proxytype == CURLPROXY_HTTP) {
|
||||
/* force this connection's protocol to become HTTP */
|
||||
conn->protocol = PROT_HTTP | bits;
|
||||
conn->bits.proxy = conn->bits.httpproxy = TRUE;
|
||||
}
|
||||
}
|
||||
} /* if(!nope) - it wasn't specified non-proxy */
|
||||
} /* NO_PROXY wasn't specified or '*' */
|
||||
if(prox && *prox) { /* don't count "" strings */
|
||||
proxy = prox; /* use this */
|
||||
}
|
||||
else {
|
||||
proxy = curl_getenv("all_proxy"); /* default proxy to use */
|
||||
if(!proxy)
|
||||
proxy=curl_getenv("ALL_PROXY");
|
||||
}
|
||||
} /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
|
||||
non-proxy */
|
||||
if(no_proxy)
|
||||
free(no_proxy);
|
||||
|
||||
@@ -3615,7 +3733,8 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
|
||||
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
|
||||
|
||||
if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
|
||||
strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME], MAX_CURL_USER_LENGTH);
|
||||
strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
|
||||
MAX_CURL_USER_LENGTH);
|
||||
proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
|
||||
}
|
||||
if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
|
||||
@@ -4103,15 +4222,28 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
and the SessionHandle */
|
||||
|
||||
conn->proxytype = data->set.proxytype; /* type */
|
||||
|
||||
#ifdef CURL_DISABLE_PROXY
|
||||
|
||||
conn->bits.proxy = FALSE;
|
||||
conn->bits.httpproxy = FALSE;
|
||||
conn->bits.proxy_user_passwd = FALSE;
|
||||
conn->bits.tunnel_proxy = FALSE;
|
||||
|
||||
#else /* CURL_DISABLE_PROXY */
|
||||
|
||||
conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] &&
|
||||
*data->set.str[STRING_PROXY]);
|
||||
conn->bits.httpproxy = (bool)(conn->bits.proxy
|
||||
&& (conn->proxytype == CURLPROXY_HTTP));
|
||||
conn->bits.httpproxy = (bool)(conn->bits.proxy &&
|
||||
(conn->proxytype == CURLPROXY_HTTP ||
|
||||
conn->proxytype == CURLPROXY_HTTP_1_0));
|
||||
conn->bits.proxy_user_passwd =
|
||||
(bool)(NULL != data->set.str[STRING_PROXYUSERNAME]);
|
||||
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
|
||||
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
||||
conn->bits.user_passwd = (bool)(NULL != data->set.str[STRING_USERNAME]);
|
||||
conn->bits.proxy_user_passwd = (bool)(NULL != data->set.str[STRING_PROXYUSERNAME]);
|
||||
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
|
||||
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
|
||||
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
|
||||
|
||||
@@ -4191,11 +4323,35 @@ static CURLcode create_conn(struct SessionHandle *data,
|
||||
|
||||
if(!proxy)
|
||||
proxy = detect_proxy(conn);
|
||||
else if(data->set.str[STRING_NOPROXY]) {
|
||||
if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
|
||||
free(proxy); /* proxy is in exception list */
|
||||
proxy = NULL;
|
||||
}
|
||||
}
|
||||
if(proxy && !*proxy) {
|
||||
free(proxy); /* Don't bother with an empty proxy string */
|
||||
proxy = NULL;
|
||||
}
|
||||
/* proxy must be freed later unless NULL */
|
||||
if(proxy && *proxy) {
|
||||
long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
|
||||
|
||||
if((conn->proxytype == CURLPROXY_HTTP) ||
|
||||
(conn->proxytype == CURLPROXY_HTTP_1_0)) {
|
||||
/* force this connection's protocol to become HTTP */
|
||||
conn->protocol = PROT_HTTP | bits;
|
||||
conn->bits.httpproxy = TRUE;
|
||||
}
|
||||
conn->bits.proxy = TRUE;
|
||||
}
|
||||
else {
|
||||
/* we aren't using the proxy after all... */
|
||||
conn->bits.proxy = FALSE;
|
||||
conn->bits.httpproxy = FALSE;
|
||||
conn->bits.proxy_user_passwd = FALSE;
|
||||
conn->bits.tunnel_proxy = FALSE;
|
||||
}
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
||||
/*************************************************************
|
||||
@@ -4667,8 +4823,12 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
state it is for re-using, so we're forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge.
|
||||
|
||||
connectindex == -1 here means that the connection has no spot in the
|
||||
connection cache and thus we must disconnect it here.
|
||||
*/
|
||||
if(data->set.reuse_forbid || conn->bits.close || premature) {
|
||||
if(data->set.reuse_forbid || conn->bits.close || premature ||
|
||||
(-1 == conn->connectindex)) {
|
||||
CURLcode res2 = Curl_disconnect(conn); /* close the connection */
|
||||
|
||||
/* If we had an error already, make sure we return that one. But
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -83,5 +83,6 @@ void Curl_close_connections(struct SessionHandle *data);
|
||||
void Curl_reset_reqproto(struct connectdata *conn);
|
||||
|
||||
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
|
||||
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi service */
|
||||
|
||||
#endif
|
||||
|
@@ -269,13 +269,7 @@ typedef enum {
|
||||
} curlntlm;
|
||||
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
/* When including these headers, you must define either SECURITY_WIN32
|
||||
* or SECURITY_KERNEL, indicating who is compiling the code.
|
||||
*/
|
||||
#define SECURITY_WIN32 1
|
||||
#include <security.h>
|
||||
#include <sspi.h>
|
||||
#include <rpc.h>
|
||||
#include "curl_sspi.h"
|
||||
#endif
|
||||
|
||||
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
|
||||
@@ -444,6 +438,9 @@ struct ftp_conn {
|
||||
size_t nread_resp; /* number of bytes currently read of a server response */
|
||||
char *linestart_resp; /* line start pointer for the FTP server response
|
||||
reader function */
|
||||
bool pending_resp; /* set TRUE when a server response is pending or in
|
||||
progress, and is cleared once the last response is
|
||||
read */
|
||||
|
||||
int count1; /* general purpose counter for the state machine */
|
||||
int count2; /* general purpose counter for the state machine */
|
||||
@@ -894,22 +891,30 @@ struct connectdata {
|
||||
long connectindex; /* what index in the connection cache connects index this
|
||||
particular struct has */
|
||||
long protocol; /* PROT_* flags concerning the protocol set */
|
||||
#define PROT_MISSING (1<<0)
|
||||
#define PROT_HTTP (1<<2)
|
||||
#define PROT_HTTPS (1<<3)
|
||||
#define PROT_FTP (1<<4)
|
||||
#define PROT_TELNET (1<<5)
|
||||
#define PROT_DICT (1<<6)
|
||||
#define PROT_LDAP (1<<7)
|
||||
#define PROT_FILE (1<<8)
|
||||
#define PROT_FTPS (1<<9)
|
||||
#define PROT_SSL (1<<10) /* protocol requires SSL */
|
||||
#define PROT_TFTP (1<<11)
|
||||
#define PROT_SCP (1<<12)
|
||||
#define PROT_SFTP (1<<13)
|
||||
#define PROT_HTTP CURLPROTO_HTTP
|
||||
#define PROT_HTTPS CURLPROTO_HTTPS
|
||||
#define PROT_FTP CURLPROTO_FTP
|
||||
#define PROT_TELNET CURLPROTO_TELNET
|
||||
#define PROT_DICT CURLPROTO_DICT
|
||||
#define PROT_LDAP CURLPROTO_LDAP
|
||||
#define PROT_FILE CURLPROTO_FILE
|
||||
#define PROT_FTPS CURLPROTO_FTPS
|
||||
#define PROT_TFTP CURLPROTO_TFTP
|
||||
#define PROT_SCP CURLPROTO_SCP
|
||||
#define PROT_SFTP CURLPROTO_SFTP
|
||||
|
||||
/* CURLPROTO_TFTP (1<<11) is currently the highest used bit in the public
|
||||
bitmask. We make sure we use "private bits" above the first 16 to make
|
||||
things easier. */
|
||||
|
||||
#define PROT_EXTMASK 0xffff
|
||||
|
||||
#define PROT_SSL (1<<22) /* protocol requires SSL */
|
||||
#define PROT_MISSING (1<<23)
|
||||
|
||||
#define PROT_CLOSEACTION PROT_FTP /* these ones need action before socket
|
||||
close */
|
||||
#define PROT_DUALCHANNEL PROT_FTP /* these protocols use two connections */
|
||||
|
||||
/* 'dns_entry' is the particular host we use. This points to an entry in the
|
||||
DNS cache and it will not get pruned while locked. It gets unlocked in
|
||||
@@ -1047,9 +1052,13 @@ struct connectdata {
|
||||
union {
|
||||
struct ftp_conn ftpc;
|
||||
struct ssh_conn sshc;
|
||||
struct tftp_state_data *tftpc;
|
||||
} proto;
|
||||
|
||||
int cselect_bits; /* bitmask of socket events */
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
int socks5_gssapi_enctype;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The end of connectdata. */
|
||||
@@ -1065,6 +1074,8 @@ struct PureInfo {
|
||||
was unretrievable. We cannot have this of type time_t,
|
||||
since time_t is unsigned on several platforms such as
|
||||
OpenVMS. */
|
||||
bool timecond; /* set to TRUE if the time condition didn't match, which
|
||||
thus made the document NOT get fetched */
|
||||
long header_size; /* size of read header(s) in bytes */
|
||||
long request_size; /* the amount of bytes sent in the request(s) */
|
||||
long proxyauthavail; /* what proxy auth types were announced */
|
||||
@@ -1288,7 +1299,7 @@ struct UrlState {
|
||||
struct HTTP *http;
|
||||
struct HTTP *https; /* alias, just for the sake of being more readable */
|
||||
struct FTP *ftp;
|
||||
void *tftp; /* private for tftp.c-eyes only */
|
||||
/* void *tftp; not used */
|
||||
struct FILEPROTO *file;
|
||||
void *telnet; /* private for telnet.c-eyes only */
|
||||
void *generic;
|
||||
@@ -1363,6 +1374,11 @@ enum dupstring {
|
||||
STRING_PASSWORD, /* <password>, if used */
|
||||
STRING_PROXYUSERNAME, /* Proxy <username>, if used */
|
||||
STRING_PROXYPASSWORD, /* Proxy <password>, if used */
|
||||
STRING_NOPROXY, /* List of hosts which should not use the proxy, if
|
||||
used */
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
STRING_SOCKS5_GSSAPI_SERVICE, /* GSSAPI service name */
|
||||
#endif
|
||||
|
||||
/* -- end of strings -- */
|
||||
STRING_LAST /* not used, just an end-of-list marker */
|
||||
@@ -1423,6 +1439,7 @@ struct UserDefined {
|
||||
long timeout; /* in milliseconds, 0 means no timeout */
|
||||
long connecttimeout; /* in milliseconds, 0 means no timeout */
|
||||
long ftp_response_timeout; /* in milliseconds, 0 means no timeout */
|
||||
long tftp_blksize ; /* in bytes, 0 means use default */
|
||||
curl_off_t infilesize; /* size of file to upload, -1 means unknown */
|
||||
long low_speed_limit; /* bytes/second */
|
||||
long low_speed_time; /* number of seconds */
|
||||
@@ -1468,6 +1485,10 @@ struct UserDefined {
|
||||
|
||||
curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
|
||||
|
||||
int ftp_create_missing_dirs; /* 1 - create directories that don't exist
|
||||
2 - the same but also allow MKD to fail once
|
||||
*/
|
||||
|
||||
/* Here follows boolean settings that define how to behave during
|
||||
this session. They are STATIC, set by libcurl users or at least initially
|
||||
and they don't change during operations. */
|
||||
@@ -1478,7 +1499,6 @@ struct UserDefined {
|
||||
bool prefer_ascii; /* ASCII rather than binary */
|
||||
bool ftp_append; /* append, not overwrite, on upload */
|
||||
bool ftp_list_only; /* switch FTP command for listing directories */
|
||||
bool ftp_create_missing_dirs; /* create directories that don't exist */
|
||||
bool ftp_use_port; /* use the FTP PORT command */
|
||||
bool hide_progress; /* don't use the progress meter */
|
||||
bool http_fail_on_error; /* fail on HTTP error codes >= 300 */
|
||||
@@ -1520,6 +1540,11 @@ struct UserDefined {
|
||||
via an HTTP proxy */
|
||||
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
|
||||
unsigned int scope; /* address scope for IPv6 */
|
||||
long allowed_protocols;
|
||||
long redir_protocols;
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
long socks5_gssapi_nec; /* flag to support nec socks5 server */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Names {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="curllib"
|
||||
Name="libcurl"
|
||||
ProjectGUID="{87EE9DA4-DE1E-4448-8324-183C98DCA588}"
|
||||
>
|
||||
<Platforms>
|
||||
@@ -31,9 +31,9 @@
|
||||
/>
|
||||
<Tool Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool Name="VCMIDLTool" PreprocessorDefinitions="NDEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\Release/curllib.tlb" HeaderFileName=""
|
||||
<Tool Name="VCMIDLTool" PreprocessorDefinitions="NDEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\Release/libcurl.tlb" HeaderFileName=""
|
||||
/>
|
||||
<Tool Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" AdditionalIncludeDirectories=".,..\include" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;BUILDING_LIBCURL" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" PrecompiledHeaderFile=".\Release/curllib.pch" AssemblerListingLocation=".\Release/" ObjectFile=".\Release/" ProgramDataBaseFileName=".\Release/" BrowseInformation="1" WarningLevel="0" SuppressStartupBanner="true" DebugInformationFormat="3"
|
||||
<Tool Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" AdditionalIncludeDirectories=".,..\include" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;BUILDING_LIBCURL" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" PrecompiledHeaderFile=".\Release/libcurl.pch" AssemblerListingLocation=".\Release/" ObjectFile=".\Release/" ProgramDataBaseFileName=".\Release/" BrowseInformation="1" WarningLevel="0" SuppressStartupBanner="true" DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
@@ -47,7 +47,7 @@
|
||||
/>
|
||||
<Tool Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Release/curllib.bsc"
|
||||
<Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Release/libcurl.bsc"
|
||||
/>
|
||||
<Tool Name="VCFxCopTool"
|
||||
/>
|
||||
@@ -72,9 +72,9 @@
|
||||
/>
|
||||
<Tool Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool Name="VCMIDLTool" PreprocessorDefinitions="_DEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\Debug/curllib.tlb" HeaderFileName=""
|
||||
<Tool Name="VCMIDLTool" PreprocessorDefinitions="_DEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\Debug/libcurl.tlb" HeaderFileName=""
|
||||
/>
|
||||
<Tool Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".,..\include" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;BUILDING_LIBCURL" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" PrecompiledHeaderFile=".\Debug/curllib.pch" AssemblerListingLocation=".\Debug/" ObjectFile=".\Debug/" ProgramDataBaseFileName=".\Debug/" BrowseInformation="1" WarningLevel="0" SuppressStartupBanner="true" DebugInformationFormat="3"
|
||||
<Tool Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".,..\include" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;BUILDING_LIBCURL" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" PrecompiledHeaderFile=".\Debug/libcurl.pch" AssemblerListingLocation=".\Debug/" ObjectFile=".\Debug/" ProgramDataBaseFileName=".\Debug/" BrowseInformation="1" WarningLevel="0" SuppressStartupBanner="true" DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
@@ -88,7 +88,7 @@
|
||||
/>
|
||||
<Tool Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Debug/curllib.bsc"
|
||||
<Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Debug/libcurl.bsc"
|
||||
/>
|
||||
<Tool Name="VCFxCopTool"
|
||||
/>
|
||||
|
5
m4/.cvsignore
Normal file
5
m4/.cvsignore
Normal file
@@ -0,0 +1,5 @@
|
||||
libtool.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
lt~obsolete.m4
|
@@ -22,7 +22,7 @@
|
||||
#***************************************************************************
|
||||
|
||||
# File version for 'aclocal' use. Keep it a single number.
|
||||
# serial 43
|
||||
# serial 45
|
||||
|
||||
|
||||
dnl CURL_INCLUDES_ARPA_INET
|
||||
@@ -124,6 +124,30 @@ curl_includes_netdb="\
|
||||
])
|
||||
|
||||
|
||||
dnl CURL_INCLUDES_POLL
|
||||
dnl -------------------------------------------------
|
||||
dnl Set up variable with list of headers that must be
|
||||
dnl included when poll.h is to be included.
|
||||
|
||||
AC_DEFUN([CURL_INCLUDES_POLL], [
|
||||
curl_includes_poll="\
|
||||
/* includes start */
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_POLL_H
|
||||
# include <poll.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
#endif
|
||||
/* includes end */"
|
||||
AC_CHECK_HEADERS(
|
||||
sys/types.h poll.h sys/poll.h,
|
||||
[], [], [$curl_includes_poll])
|
||||
])
|
||||
|
||||
|
||||
dnl CURL_INCLUDES_SETJMP
|
||||
dnl -------------------------------------------------
|
||||
dnl Set up variable with list of headers that must be
|
||||
@@ -3108,6 +3132,132 @@ AC_DEFUN([CURL_CHECK_FUNC_LOCALTIME_R], [
|
||||
])
|
||||
|
||||
|
||||
dnl CURL_CHECK_FUNC_POLL
|
||||
dnl -------------------------------------------------
|
||||
dnl Verify if poll is available, prototyped, can
|
||||
dnl be compiled and seems to work. If all of these are
|
||||
dnl true, and usage has not been previously disallowed
|
||||
dnl with shell variable curl_disallow_poll, then
|
||||
dnl HAVE_POLL will be defined.
|
||||
|
||||
AC_DEFUN([CURL_CHECK_FUNC_POLL], [
|
||||
AC_REQUIRE([CURL_INCLUDES_STDLIB])dnl
|
||||
AC_REQUIRE([CURL_INCLUDES_POLL])dnl
|
||||
#
|
||||
tst_links_poll="unknown"
|
||||
tst_proto_poll="unknown"
|
||||
tst_compi_poll="unknown"
|
||||
tst_works_poll="unknown"
|
||||
tst_allow_poll="unknown"
|
||||
#
|
||||
case $host_os in
|
||||
darwin*)
|
||||
dnl poll does not work on this platform
|
||||
curl_disallow_poll="yes"
|
||||
;;
|
||||
esac
|
||||
#
|
||||
AC_MSG_CHECKING([if poll can be linked])
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
$curl_includes_poll
|
||||
]],[[
|
||||
if(0 != poll(0, 0, 0))
|
||||
return 1;
|
||||
]])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
tst_links_poll="yes"
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
tst_links_poll="no"
|
||||
])
|
||||
#
|
||||
if test "$tst_links_poll" = "yes"; then
|
||||
AC_MSG_CHECKING([if poll is prototyped])
|
||||
AC_EGREP_CPP([poll],[
|
||||
$curl_includes_poll
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
tst_proto_poll="yes"
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
tst_proto_poll="no"
|
||||
])
|
||||
fi
|
||||
#
|
||||
if test "$tst_proto_poll" = "yes"; then
|
||||
AC_MSG_CHECKING([if poll is compilable])
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
$curl_includes_poll
|
||||
]],[[
|
||||
if(0 != poll(0, 0, 0))
|
||||
return 1;
|
||||
]])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
tst_compi_poll="yes"
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
tst_compi_poll="no"
|
||||
])
|
||||
fi
|
||||
#
|
||||
dnl only do runtime verification when not cross-compiling
|
||||
if test "x$cross_compiling" != "xyes" &&
|
||||
test "$tst_compi_poll" = "yes"; then
|
||||
AC_MSG_CHECKING([if poll seems to work])
|
||||
AC_RUN_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
$curl_includes_stdlib
|
||||
$curl_includes_poll
|
||||
]],[[
|
||||
if(0 != poll(0, 0, 10))
|
||||
exit(1); /* fail */
|
||||
else
|
||||
exit(0);
|
||||
]])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
tst_works_poll="yes"
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
tst_works_poll="no"
|
||||
])
|
||||
fi
|
||||
#
|
||||
if test "$tst_compi_poll" = "yes" &&
|
||||
test "$tst_works_poll" != "no"; then
|
||||
AC_MSG_CHECKING([if poll usage allowed])
|
||||
if test "x$curl_disallow_poll" != "xyes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
tst_allow_poll="yes"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
tst_allow_poll="no"
|
||||
fi
|
||||
fi
|
||||
#
|
||||
AC_MSG_CHECKING([if poll might be used])
|
||||
if test "$tst_links_poll" = "yes" &&
|
||||
test "$tst_proto_poll" = "yes" &&
|
||||
test "$tst_compi_poll" = "yes" &&
|
||||
test "$tst_allow_poll" = "yes" &&
|
||||
test "$tst_works_poll" != "no"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE_UNQUOTED(HAVE_POLL, 1,
|
||||
[Define to 1 if you have a working poll function.])
|
||||
AC_DEFINE_UNQUOTED(HAVE_POLL_FINE, 1,
|
||||
[If you have a fine poll])
|
||||
ac_cv_func_poll="yes"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
ac_cv_func_poll="no"
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl CURL_CHECK_FUNC_SETSOCKOPT
|
||||
dnl -------------------------------------------------
|
||||
dnl Verify if setsockopt is available, prototyped, and
|
||||
|
33
maketgz
33
maketgz
@@ -1,5 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Script to build release-archives with
|
||||
# Script to build release-archives with. Note that this requires a checkout
|
||||
# from CVS and you should first run ./buildconf and build curl once.
|
||||
#
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
@@ -60,13 +61,12 @@ sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g'
|
||||
# Replace version number in header file:
|
||||
sed 's/#define CURL_VERSION .*/#define CURL_VERSION "'$curlversion'"/g' $CHEADER >$CHEADER.dist
|
||||
|
||||
echo "generate VC8 makefiles"
|
||||
# Generate VC8 versions from the VC6 Makefile versions
|
||||
make -f Makefile.dist vc8
|
||||
|
||||
echo "generate VC9 makefiles"
|
||||
# Generate VC9 versions from the VC6 Makefile versions
|
||||
make -f Makefile.dist vc9
|
||||
# Generate VC8 and VC9 versions from the VC6 Makefile versions
|
||||
for ver in vc8 vc9; do
|
||||
make -f Makefile.dist $ver
|
||||
mv src/Makefile.$ver src/Makefile.$ver.dist
|
||||
mv lib/Makefile.$ver lib/Makefile.$ver.dist
|
||||
done
|
||||
|
||||
# Replace version number in plist file:
|
||||
PLIST=lib/libcurl.plist
|
||||
@@ -143,7 +143,16 @@ make -s dist VERSION=$version
|
||||
|
||||
bzip2="curl-$version.tar.bz2"
|
||||
echo "Generating $bzip2"
|
||||
gzip -dc $targz | bzip2 - > $bzip2
|
||||
gzip -dc $targz | bzip2 --best - > $bzip2
|
||||
|
||||
############################################################################
|
||||
#
|
||||
# Now make an lzma archive from the tar.gz original
|
||||
#
|
||||
|
||||
lzma="curl-$version.tar.lzma"
|
||||
echo "Generating $lzma"
|
||||
gzip -dc $targz | lzma --best - > $lzma
|
||||
|
||||
############################################################################
|
||||
#
|
||||
@@ -169,9 +178,7 @@ makezip
|
||||
echo "------------------"
|
||||
echo "maketgz report:"
|
||||
echo ""
|
||||
ls -l $targz $bzip2 $zip
|
||||
|
||||
md5sum $targz $bzip2 $zip
|
||||
ls -l $targz $bzip2 $zip $lzma
|
||||
|
||||
echo "Run this:"
|
||||
echo "gpg -b -a $targz && gpg -b -a $bzip2 && gpg -b -a $zip"
|
||||
echo "gpg -b -a $targz && gpg -b -a $bzip2 && gpg -b -a $zip && gpg -b -a $lzma"
|
||||
|
@@ -105,6 +105,8 @@ options:
|
||||
CURLOPT_PASSWORD
|
||||
CURLOPT_PROXYUSERNAME
|
||||
CURLOPT_PROXYPASSWORD
|
||||
CURLOPT_NOPROXY
|
||||
CURLOPT_SOCKS5_GSSAPI_SERVICE
|
||||
Else it is the same as for curl_easy_setopt().
|
||||
Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the
|
||||
address of an (empty) character buffer, not the address of a string.
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -1030,7 +1030,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
if (testwarn) {
|
||||
testwarn = 0;
|
||||
|
||||
if ((int) STRING_LAST != (int) STRING_PROXYPASSWORD + 1)
|
||||
if ((int) STRING_LAST != (int) STRING_SOCKS5_GSSAPI_SERVICE + 1)
|
||||
curl_mfprintf(stderr,
|
||||
"*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n");
|
||||
}
|
||||
@@ -1079,6 +1079,8 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
case CURLOPT_PASSWORD:
|
||||
case CURLOPT_PROXYUSERNAME:
|
||||
case CURLOPT_PROXYPASSWORD:
|
||||
case CURLOPT_NOPROXY:
|
||||
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
|
||||
s = va_arg(arg, char *);
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -131,7 +131,7 @@
|
||||
d c X'00000010'
|
||||
d CURLAUTH_ANY c X'7FFFFFEF'
|
||||
d CURLAUTH_ANYSAFE...
|
||||
d c X'7FFFFFEE' ~CURLAUTH_BASIC
|
||||
d c X'7FFFFFEE'
|
||||
*
|
||||
d CURLSSH_AUTH_ANY...
|
||||
d c X'7FFFFFFF'
|
||||
@@ -433,6 +433,8 @@
|
||||
d curl_proxytype s 10i 0 based(######ptr######) Enum
|
||||
d CURLPROXY_HTTP...
|
||||
d c 0
|
||||
d CURLPROXY_HTTP_1_0...
|
||||
d c 1
|
||||
d CURLPROXY_SOCKS4...
|
||||
d c 4
|
||||
d CURLPROXY_SOCKS5...
|
||||
@@ -466,6 +468,15 @@
|
||||
d CURLFTPAUTH_SSL...
|
||||
d c 1
|
||||
d CURLFTPAUTH_TLS...
|
||||
d c 2
|
||||
*
|
||||
d curl_ftpcreatedir...
|
||||
d s 10i 0 based(######ptr######) Enum
|
||||
d CURLFTP_CREATE_DIR_NONE...
|
||||
d c 0
|
||||
d CURLFTP_CREATE_DIR...
|
||||
d c 1
|
||||
d CURLFTP_CREATE_DIR_RETRY...
|
||||
d c 2
|
||||
*
|
||||
d curl_ftpmethod s 10i 0 based(######ptr######) Enum
|
||||
@@ -792,6 +803,14 @@
|
||||
d c 10175
|
||||
d CURLOPT_PROXYPASSWORD...
|
||||
d c 10176
|
||||
d CURLOPT_NOPROXY...
|
||||
d c 10177
|
||||
d CURLOPT_TFTP_BLKSIZE...
|
||||
d c 00178
|
||||
d CURLOPT_SOCKS5_GSSAPI_SERVICE...
|
||||
d c 00179
|
||||
d CURLOPT_SOCKS5_GSSAPI_NEC...
|
||||
d c 00180
|
||||
*
|
||||
d CURLOPT_POST301...
|
||||
d c 00161 Obsolescent
|
||||
@@ -925,6 +944,8 @@
|
||||
d c X'00300021'
|
||||
d CURLINFO_CERTINFO... CURLINFO_SLIST + 34
|
||||
d c X'00400022'
|
||||
d CURLINFO_CONDITION_UNMET... CURLINFO_LONG + 35
|
||||
d c X'00200023'
|
||||
*
|
||||
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
|
||||
d c X'00200002'
|
||||
|
@@ -156,7 +156,7 @@ db2_name()
|
||||
|
||||
{
|
||||
basename "${1}" |
|
||||
tr '[a-z-]' '[A-Z_]' |
|
||||
tr '[a-z-]' '[A-Z_]' |
|
||||
sed -e 's/\..*//' \
|
||||
-e 's/^\(..........\).*/\1/'
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ cd "${TOPDIR}/lib"
|
||||
|
||||
echo '#pragma comment(user, "libcurl version '"${LIBCURL_VERSION}"'")' > os400.c
|
||||
echo '#pragma comment(date)' >> os400.c
|
||||
echo '#pragma comment(copyright, "Copyright (C) 1998-2008 Daniel Stenberg et al. OS/400 version by P. Monnerat")' >> os400.c
|
||||
echo '#pragma comment(copyright, "Copyright (C) 1998-2009 Daniel Stenberg et al. OS/400 version by P. Monnerat")' >> os400.c
|
||||
make_module OS400 os400.c
|
||||
LINK= # No need to rebuild service program yet.
|
||||
MODULES=
|
||||
|
@@ -120,8 +120,11 @@ COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
|
||||
include Makefile.inc
|
||||
|
||||
curl_OBJECTS := $(patsubst %.c,%.o,$(strip $(CURL_SOURCES)))
|
||||
# curlx_OBJECTS := $(patsubst %.c,%.o,$(notdir $(strip $(CURLX_ONES))))
|
||||
# vpath %.c ../lib
|
||||
ifdef DYN
|
||||
curlx_OBJECTS := $(patsubst %.c,%.o,$(notdir $(strip $(CURLX_ONES))))
|
||||
curl_OBJECTS += $(curlx_OBJECTS)
|
||||
vpath %.c ../lib
|
||||
endif
|
||||
|
||||
RESOURCE = curl.res
|
||||
|
||||
|
@@ -263,22 +263,39 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* VS2008 does not support Windows build targets prior to WinXP, */
|
||||
/* so, if no build target has been defined we will target WinXP. */
|
||||
/* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
|
||||
2000 as a supported build target. VS2008 default installations provide an
|
||||
embedded Windows SDK v6.0A along with the claim that Windows 2000 is a
|
||||
valid build target for VS2008. Popular belief is that binaries built using
|
||||
Windows SDK versions 6.X and Windows 2000 as a build target are functional */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define VS2008_MINIMUM_TARGET 0x0500
|
||||
#endif
|
||||
|
||||
/* When no build target is specified VS2008 default build target is Windows
|
||||
Vista, which leaves out even Winsows XP. If no build target has been given
|
||||
for VS2008 we will target the minimum Officially supported build target,
|
||||
which happens to be Windows XP. */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# define VS2008_DEFAULT_TARGET 0x0501
|
||||
#endif
|
||||
|
||||
/* VS2008 default target settings and minimum build target check */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# define _WIN32_WINNT VS2008_DEFAULT_TARGET
|
||||
# endif
|
||||
# ifndef WINVER
|
||||
# define WINVER 0x0501
|
||||
# define WINVER VS2008_DEFAULT_TARGET
|
||||
# endif
|
||||
# if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501)
|
||||
# error VS2008 does not support Windows build targets prior to WinXP
|
||||
# if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
|
||||
# error VS2008 does not support Windows build targets prior to Windows 2000
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is quite */
|
||||
/* convoluted, compiler dependant and in some cases even build target dependat. */
|
||||
/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is
|
||||
quite convoluted, compiler dependant and in some cases even build target
|
||||
dependant. */
|
||||
#if defined(HAVE_WS2TCPIP_H)
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
|
||||
# define HAVE_FREEADDRINFO 1
|
||||
|
87
src/main.c
87
src/main.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2009, 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
|
||||
@@ -448,6 +448,8 @@ struct Configurable {
|
||||
char *userpwd;
|
||||
char *proxyuserpwd;
|
||||
char *proxy;
|
||||
int proxyver; /* set to CURLPROXY_HTTP* define */
|
||||
char *noproxy;
|
||||
bool proxytunnel;
|
||||
bool ftp_append; /* APPE on ftp */
|
||||
bool mute; /* shutup */
|
||||
@@ -535,6 +537,10 @@ struct Configurable {
|
||||
|
||||
char *socksproxy; /* set to server string */
|
||||
int socksver; /* set to CURLPROXY_SOCKS* define */
|
||||
char *socks5_gssapi_service; /* set service name for gssapi principal
|
||||
* default rcmd */
|
||||
int socks5_gssapi_nec ; /* The NEC reference server does not protect
|
||||
* the encryption type exchange */
|
||||
|
||||
bool tcp_nodelay;
|
||||
long req_retry; /* number of retries */
|
||||
@@ -772,6 +778,7 @@ static void help(void)
|
||||
" -N/--no-buffer Disable buffering of the output stream",
|
||||
" --no-keepalive Disable keepalive use on the connection",
|
||||
" --no-sessionid Disable SSL session-ID reusing (SSL)",
|
||||
" --noproxy Comma-separated list of hosts which do not use proxy",
|
||||
" --ntlm Use HTTP NTLM authentication (H)",
|
||||
" -o/--output <file> Write output to <file> instead of stdout",
|
||||
" --pass <pass> Pass phrase for the private key (SSL/SSH)",
|
||||
@@ -785,6 +792,7 @@ static void help(void)
|
||||
" --proxy-negotiate Use Negotiate authentication on the proxy (H)",
|
||||
" --proxy-ntlm Use NTLM authentication on the proxy (H)",
|
||||
" -U/--proxy-user <user[:password]> Set proxy user and password",
|
||||
" --proxy1.0 <host[:port]> Use HTTP/1.0 proxy on given port",
|
||||
" -p/--proxytunnel Operate through a HTTP proxy tunnel (using CONNECT)",
|
||||
" --pubkey <key> Public key file name (SSH)",
|
||||
" -Q/--quote <cmd> Send command(s) to server before file transfer (F/SFTP)",
|
||||
@@ -805,6 +813,10 @@ static void help(void)
|
||||
" --socks4a <host[:port]> SOCKS4a proxy on given host + port",
|
||||
" --socks5 <host[:port]> SOCKS5 proxy on given host + port",
|
||||
" --socks5-hostname <host[:port]> SOCKS5 proxy, pass host name to proxy",
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
" --socks5-gssapi-service <name> SOCKS5 proxy service name for gssapi",
|
||||
" --socks5-gssapi-nec Compatibility with NEC SOCKS5 server",
|
||||
#endif
|
||||
" -Y/--speed-limit Stop transfer if below speed-limit for 'speed-time' secs",
|
||||
" -y/--speed-time Time needed to trig speed-limit abort. Defaults to 30",
|
||||
" -2/--sslv2 Use SSLv2 (SSL)",
|
||||
@@ -1666,6 +1678,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
{"$2", "socks5-hostname", TRUE},
|
||||
{"$3", "keepalive-time", TRUE},
|
||||
{"$4", "post302", FALSE},
|
||||
{"$5", "noproxy", TRUE},
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
{"$6", "socks5-gssapi-service", TRUE},
|
||||
{"$7", "socks5-gssapi-nec", FALSE},
|
||||
#endif
|
||||
{"$8", "proxy1.0", TRUE},
|
||||
|
||||
{"0", "http1.0", FALSE},
|
||||
{"1", "tlsv1", FALSE},
|
||||
@@ -2175,6 +2193,23 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case '4': /* --post302 */
|
||||
config->post302 = toggle;
|
||||
break;
|
||||
case '5': /* --noproxy */
|
||||
/* This specifies the noproxy list */
|
||||
GetStr(&config->noproxy, nextarg);
|
||||
break;
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
case '6': /* --socks5-gssapi-service */
|
||||
GetStr(&config->socks5_gssapi_service, nextarg);
|
||||
break;
|
||||
case '7': /* --socks5-gssapi-nec*/
|
||||
config->socks5_gssapi_nec = TRUE;
|
||||
break;
|
||||
#endif
|
||||
case '8': /* --proxy1.0 */
|
||||
/* http 1.0 proxy */
|
||||
GetStr(&config->proxy, nextarg);
|
||||
config->proxyver = CURLPROXY_HTTP_1_0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '#': /* --progress-bar */
|
||||
@@ -2860,6 +2895,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'x':
|
||||
/* proxy */
|
||||
GetStr(&config->proxy, nextarg);
|
||||
config->proxyver = CURLPROXY_HTTP;
|
||||
break;
|
||||
case 'X':
|
||||
/* set custom request */
|
||||
@@ -3641,6 +3677,8 @@ static void free_config_fields(struct Configurable *config)
|
||||
free(config->proxy);
|
||||
if(config->proxyuserpwd)
|
||||
free(config->proxyuserpwd);
|
||||
if(config->noproxy)
|
||||
free(config->noproxy);
|
||||
if(config->cookie)
|
||||
free(config->cookie);
|
||||
if(config->cookiefile)
|
||||
@@ -3691,6 +3729,10 @@ static void free_config_fields(struct Configurable *config)
|
||||
free(config->referer);
|
||||
if (config->hostpubmd5)
|
||||
free(config->hostpubmd5);
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(config->socks5_gssapi_service)
|
||||
free(config->socks5_gssapi_service);
|
||||
#endif
|
||||
|
||||
curl_slist_free_all(config->quote); /* checks for config->quote == NULL */
|
||||
curl_slist_free_all(config->prequote);
|
||||
@@ -4534,6 +4576,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
|
||||
my_setopt(curl, CURLOPT_URL, url); /* what to fetch */
|
||||
my_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */
|
||||
if(config->proxy)
|
||||
my_setopt(curl, CURLOPT_PROXYTYPE, config->proxyver);
|
||||
my_setopt(curl, CURLOPT_NOPROGRESS, config->noprogress);
|
||||
if(config->no_body) {
|
||||
my_setopt(curl, CURLOPT_NOBODY, 1);
|
||||
@@ -4559,6 +4603,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
|
||||
my_setopt(curl, CURLOPT_USERPWD, config->userpwd);
|
||||
my_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
|
||||
my_setopt(curl, CURLOPT_NOPROXY, config->noproxy);
|
||||
my_setopt(curl, CURLOPT_RANGE, config->range);
|
||||
my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
|
||||
my_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
|
||||
@@ -4708,11 +4753,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
|
||||
/* new in curl 7.10 */
|
||||
my_setopt(curl, CURLOPT_ENCODING,
|
||||
(config->encoding) ? "" : NULL);
|
||||
(config->encoding) ? "" : NULL);
|
||||
|
||||
/* new in curl 7.10.7 */
|
||||
/* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
|
||||
my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
|
||||
config->ftp_create_dirs);
|
||||
config->ftp_create_dirs);
|
||||
if(config->proxyanyauth)
|
||||
my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
|
||||
else if(config->proxynegotiate)
|
||||
@@ -4758,6 +4803,16 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
my_setopt(curl, CURLOPT_PROXYTYPE, config->socksver);
|
||||
}
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
/* new in curl 7.19.4 */
|
||||
if(config->socks5_gssapi_service)
|
||||
my_setopt(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
|
||||
config->socks5_gssapi_service);
|
||||
|
||||
/* new in curl 7.19.4 */
|
||||
if(config->socks5_gssapi_nec)
|
||||
my_setopt(curl, CURLOPT_SOCKS5_GSSAPI_NEC, config->socks5_gssapi_nec);
|
||||
#endif
|
||||
/* curl 7.13.0 */
|
||||
my_setopt(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
|
||||
|
||||
@@ -4870,17 +4925,13 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
}
|
||||
|
||||
if(retry) {
|
||||
static const char * const m[]={NULL,
|
||||
"timeout",
|
||||
"HTTP error",
|
||||
"FTP error"
|
||||
static const char * const m[]={
|
||||
NULL, "timeout", "HTTP error", "FTP error"
|
||||
};
|
||||
warnf(config, "Transient problem: %s "
|
||||
"Will retry in %ld seconds. "
|
||||
"%ld retries left.\n",
|
||||
m[retry],
|
||||
retry_sleep/1000,
|
||||
retry_numretries);
|
||||
m[retry], retry_sleep/1000, retry_numretries);
|
||||
|
||||
go_sleep(retry_sleep);
|
||||
retry_numretries--;
|
||||
@@ -4922,15 +4973,13 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
} while(1);
|
||||
|
||||
if((config->progressmode == CURL_PROGRESS_BAR) &&
|
||||
progressbar.calls) {
|
||||
progressbar.calls)
|
||||
/* if the custom progress bar has been displayed, we output a
|
||||
newline here */
|
||||
fputs("\n", progressbar.out);
|
||||
}
|
||||
|
||||
if(config->writeout) {
|
||||
if(config->writeout)
|
||||
ourWriteOut(curl, config->writeout);
|
||||
}
|
||||
#ifdef USE_ENVIRONMENT
|
||||
if (config->writeenv)
|
||||
ourWriteEnv(curl);
|
||||
@@ -5295,12 +5344,14 @@ static char *basename(char *path)
|
||||
static const char *
|
||||
msdosify (const char *file_name)
|
||||
{
|
||||
static char dos_name[PATH_MAX*2];
|
||||
static const char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*";
|
||||
static char dos_name[PATH_MAX];
|
||||
static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
|
||||
"|<>\\\":?*"; /* illegal in DOS & W95 */
|
||||
static const char *illegal_chars_w95 = &illegal_chars_dos[8];
|
||||
int idx, dot_idx;
|
||||
const char *s = file_name;
|
||||
char *d = dos_name;
|
||||
const char * const dlimit = dos_name + sizeof(dos_name) - 1;
|
||||
const char *illegal_aliens = illegal_chars_dos;
|
||||
size_t len = sizeof (illegal_chars_dos) - 1;
|
||||
int lfn = 0;
|
||||
@@ -5321,7 +5372,7 @@ msdosify (const char *file_name)
|
||||
*d++ = *s++;
|
||||
}
|
||||
|
||||
for (idx = 0, dot_idx = -1; *s; s++, d++) {
|
||||
for (idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
|
||||
if (memchr (illegal_aliens, *s, len)) {
|
||||
/* Dots are special: DOS doesn't allow them as the leading character,
|
||||
and a file name cannot have more than a single dot. We leave the
|
||||
|
@@ -60,7 +60,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
|
||||
test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 \
|
||||
test1080 test1081 test1082 test1083 test1084 test1085 test633 test634 \
|
||||
test635 test636 test637 test558 test559 test1086 test1087 test1088 \
|
||||
test1089 test1090
|
||||
test1089 test1090 test1091 test1092 test1093 test1094 test1095 test1096
|
||||
|
||||
filecheck:
|
||||
@mkdir test-place; \
|
||||
|
@@ -102,12 +102,12 @@ http://test.remote.server.com:1008/path/10080002 --proxy http://%HOSTIP:%HTTPPOR
|
||||
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
|
||||
</strippart>
|
||||
<protocol>
|
||||
CONNECT test.remote.server.com:1008 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1008 HTTP/1.1
|
||||
Host: test.remote.server.com:1008
|
||||
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:1008 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1008 HTTP/1.1
|
||||
Host: test.remote.server.com:1008
|
||||
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
@@ -111,16 +111,16 @@ http://test.remote.server.com:1021/path/10210002 --proxy http://%HOSTIP:%HTTPPOR
|
||||
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
|
||||
</strippart>
|
||||
<protocol>
|
||||
CONNECT test.remote.server.com:1021 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1021 HTTP/1.1
|
||||
Host: test.remote.server.com:1021
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:1021 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1021 HTTP/1.1
|
||||
Host: test.remote.server.com:1021
|
||||
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:1021 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1021 HTTP/1.1
|
||||
Host: test.remote.server.com:1021
|
||||
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
@@ -49,7 +49,7 @@ ftp://test-number:1059/wanted/page -p -x %HOSTIP:%HTTPPORT
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
CONNECT test-number:1059 HTTP/1.0
|
||||
CONNECT test-number:1059 HTTP/1.1
|
||||
Host: test-number:1059
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
|
@@ -884,11 +884,11 @@ http://test.remote.server.com:1060/path/10600002 --proxy http://%HOSTIP:%HTTPPOR
|
||||
^User-Agent: curl/.*
|
||||
</strip>
|
||||
<protocol>
|
||||
CONNECT test.remote.server.com:1060 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1060 HTTP/1.1
|
||||
Host: test.remote.server.com:1060
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:1060 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1060 HTTP/1.1
|
||||
Host: test.remote.server.com:1060
|
||||
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:1060", response="b527d164630481e2cc48c04d18ed2212"
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
@@ -889,11 +889,11 @@ http://test.remote.server.com:1061/path/10610002 --proxy http://%HOSTIP:%HTTPPOR
|
||||
^User-Agent: curl/.*
|
||||
</strip>
|
||||
<protocol>
|
||||
CONNECT test.remote.server.com:1061 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1061 HTTP/1.1
|
||||
Host: test.remote.server.com:1061
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:1061 HTTP/1.0
|
||||
CONNECT test.remote.server.com:1061 HTTP/1.1
|
||||
Host: test.remote.server.com:1061
|
||||
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:1061", response="244a8caab5f343a1a20d2425e4d6e951"
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
@@ -33,10 +33,10 @@ contents
|
||||
http
|
||||
</server>
|
||||
<name>
|
||||
HTTP CONNECT with proxytunnel and downgrade to HTTP/1.0
|
||||
HTTP 1.0 CONNECT with proxytunnel and downgrade GET to HTTP/1.0
|
||||
</name>
|
||||
<command>
|
||||
-x %HOSTIP:%HTTPPORT -p http://%HOSTIP:%HTTPPORT/we/want/that/page/1078 http://%HOSTIP:%HTTPPORT/we/want/that/page/1078
|
||||
--proxy1.0 %HOSTIP:%HTTPPORT -p http://%HOSTIP:%HTTPPORT/we/want/that/page/1078 http://%HOSTIP:%HTTPPORT/we/want/that/page/1078
|
||||
</command>
|
||||
</client>
|
||||
|
||||
|
46
tests/data/test1091
Normal file
46
tests/data/test1091
Normal file
@@ -0,0 +1,46 @@
|
||||
<testcase>
|
||||
# based on test 143
|
||||
<info>
|
||||
<keywords>
|
||||
FTP
|
||||
RETR
|
||||
type=
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
bla bla bla
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
ftp
|
||||
</server>
|
||||
<name>
|
||||
FTP URL with type=i
|
||||
</name>
|
||||
<command>
|
||||
"ftp://%HOSTIP:%FTPPORT/%2ftmp/moo/1091;type=i" --use-ascii
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
USER anonymous
|
||||
PASS ftp@example.com
|
||||
PWD
|
||||
CWD /tmp
|
||||
CWD moo
|
||||
EPSV
|
||||
TYPE I
|
||||
SIZE 1091
|
||||
RETR 1091
|
||||
QUIT
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
56
tests/data/test1092
Normal file
56
tests/data/test1092
Normal file
@@ -0,0 +1,56 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
FTP
|
||||
HTTP
|
||||
HTTP GET
|
||||
HTTP proxy
|
||||
type=
|
||||
</keywords>
|
||||
</info>
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.0 200 OK
|
||||
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||
Server: test-server/fake swsclose
|
||||
Content-Type: text/html
|
||||
Funny-head: yesyes
|
||||
|
||||
contents
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
ftp
|
||||
</features>
|
||||
<name>
|
||||
FTP with type=i over HTTP proxy
|
||||
</name>
|
||||
<command>
|
||||
"ftp://%HOSTIP:%HTTPPORT/we/want/that/page/1092;type=i" --use-ascii -x %HOSTIP:%HTTPPORT
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET ftp://%HOSTIP:%HTTPPORT/we/want/that/page/1092;type=i HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
44
tests/data/test1093
Normal file
44
tests/data/test1093
Normal file
@@ -0,0 +1,44 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
TFTP
|
||||
TFTP RRQ
|
||||
mode=
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
a chunk of
|
||||
data
|
||||
returned
|
||||
to client
|
||||
</data>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
tftp
|
||||
</server>
|
||||
<name>
|
||||
TFTP retrieve with mode=i
|
||||
</name>
|
||||
<command>
|
||||
"tftp://%HOSTIP:%TFTPPORT//1093;mode=i" --use-ascii --trace-ascii log/traceit
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify pseudo protocol after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
opcode: 1
|
||||
filename: /1093
|
||||
mode: octet
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
50
tests/data/test1094
Normal file
50
tests/data/test1094
Normal file
@@ -0,0 +1,50 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
TFTP
|
||||
TFTP RRQ
|
||||
mode=
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
#
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
a chunk of
|
||||
data
|
||||
returned
|
||||
to client
|
||||
</data>
|
||||
<datacheck>
|
||||
a chunk of
|
||||
data
|
||||
returned
|
||||
to client
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
tftp
|
||||
</server>
|
||||
<name>
|
||||
TFTP retrieve with mode=netascii
|
||||
</name>
|
||||
<command>
|
||||
"tftp://%HOSTIP:%TFTPPORT//1094;mode=netascii" --trace-ascii log/traceit
|
||||
</command>
|
||||
</client>
|
||||
|
||||
#
|
||||
# Verify pseudo protocol after the test has been "shot"
|
||||
<verify>
|
||||
<protocol>
|
||||
opcode: 1
|
||||
filename: /1094
|
||||
mode: netascii
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
83
tests/data/test1095
Normal file
83
tests/data/test1095
Normal file
@@ -0,0 +1,83 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
HTTP
|
||||
HTTP GET
|
||||
HTTP Digest auth
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<data>
|
||||
HTTP/1.1 401 Authorization Required swsclose
|
||||
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||
WWW-Authenticate: Digest realm="test \"this\" realm!!", nonce="1053604145"
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Length: 26
|
||||
|
||||
This is not the real page
|
||||
</data>
|
||||
|
||||
# This is supposed to be returned when the server gets a
|
||||
# Authorization: Digest line passed-in from the client
|
||||
<data1000>
|
||||
HTTP/1.1 200 OK swsclose
|
||||
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Length: 23
|
||||
|
||||
This IS the real page!
|
||||
</data1000>
|
||||
|
||||
<datacheck>
|
||||
HTTP/1.1 401 Authorization Required swsclose
|
||||
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||
WWW-Authenticate: Digest realm="test \"this\" realm!!", nonce="1053604145"
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Length: 26
|
||||
|
||||
HTTP/1.1 200 OK swsclose
|
||||
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Length: 23
|
||||
|
||||
This IS the real page!
|
||||
</datacheck>
|
||||
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
http
|
||||
</server>
|
||||
<features>
|
||||
crypto
|
||||
</features>
|
||||
<name>
|
||||
HTTP with Digest and realm with quoted quotes
|
||||
</name>
|
||||
<command>
|
||||
http://%HOSTIP:%HTTPPORT/1095 -u testuser:testpass --digest
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<strip>
|
||||
^User-Agent:.*
|
||||
</strip>
|
||||
<protocol>
|
||||
GET /1095 HTTP/1.1
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
GET /1095 HTTP/1.1
|
||||
Authorization: Digest username="testuser", realm="test \"this\" realm!!", nonce="1053604145", uri="/1095", response="a1c7931ece9e8617bae2715045e4f49f"
|
||||
User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 zlib/1.1.3
|
||||
Host: %HOSTIP:%HTTPPORT
|
||||
Accept: */*
|
||||
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
50
tests/data/test1096
Normal file
50
tests/data/test1096
Normal file
@@ -0,0 +1,50 @@
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
FTP
|
||||
PASV
|
||||
RETR
|
||||
FAILURE
|
||||
</keywords>
|
||||
</info>
|
||||
# Server-side
|
||||
<reply>
|
||||
<servercmd>
|
||||
REPLY RETR 550 no such file!
|
||||
</servercmd>
|
||||
</reply>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
ftp
|
||||
</server>
|
||||
<name>
|
||||
Two FTP downloads, with failed RETR but re-used control connection
|
||||
</name>
|
||||
<command>
|
||||
ftp://%HOSTIP:%FTPPORT/dir/1096 ftp://%HOSTIP:%FTPPORT/dir/1096
|
||||
</command>
|
||||
</client>
|
||||
|
||||
# Verify data after the test has been "shot"
|
||||
<verify>
|
||||
<errorcode>
|
||||
78
|
||||
</errorcode>
|
||||
<protocol>
|
||||
USER anonymous
|
||||
PASS ftp@example.com
|
||||
PWD
|
||||
CWD dir
|
||||
EPSV
|
||||
TYPE I
|
||||
SIZE 1096
|
||||
RETR 1096
|
||||
EPSV
|
||||
SIZE 1096
|
||||
RETR 1096
|
||||
QUIT
|
||||
</protocol>
|
||||
</verify>
|
||||
</testcase>
|
@@ -81,11 +81,11 @@ http://test.remote.server.com:206/path/2060002 --proxy http://%HOSTIP:%HTTPPORT
|
||||
^User-Agent: curl/.*
|
||||
</strip>
|
||||
<protocol>
|
||||
CONNECT test.remote.server.com:206 HTTP/1.0
|
||||
CONNECT test.remote.server.com:206 HTTP/1.1
|
||||
Host: test.remote.server.com:206
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:206 HTTP/1.0
|
||||
CONNECT test.remote.server.com:206 HTTP/1.1
|
||||
Host: test.remote.server.com:206
|
||||
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:206", response="5059a96c954981ceb94e17d667c8d3f8"
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
@@ -95,12 +95,12 @@ http://test.remote.server.com:209/path/2090002 --proxy http://%HOSTIP:%HTTPPORT
|
||||
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
|
||||
</strippart>
|
||||
<protocol>
|
||||
CONNECT test.remote.server.com:209 HTTP/1.0
|
||||
CONNECT test.remote.server.com:209 HTTP/1.1
|
||||
Host: test.remote.server.com:209
|
||||
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
||||
CONNECT test.remote.server.com:209 HTTP/1.0
|
||||
CONNECT test.remote.server.com:209 HTTP/1.1
|
||||
Host: test.remote.server.com:209
|
||||
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
|
||||
Proxy-Connection: Keep-Alive
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user