Compare commits

...

105 Commits

Author SHA1 Message Date
Daniel Stenberg
042cc1f69e - 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.
2009-03-02 23:05:31 +00:00
Daniel Stenberg
90b804d3fa 7.19.4 won't get anything else 2009-03-02 10:43:46 +00:00
Daniel Stenberg
4bc603a0cc the Eiffel binding 2009-03-02 09:03:11 +00:00
Daniel Stenberg
6c3f74b946 nothing more left for 7.19.4, the issue #216 is moved to 7.19.5 since we're
too close to release now
2009-03-01 14:20:26 +00:00
Yang Tse
8d78a33e60 for portability reasons: s/inet_pton/Curl_inet_pton/ 2009-02-28 01:35:53 +00:00
Yang Tse
df07537ccf fix compiler warning 2009-02-28 01:11:57 +00:00
Daniel Stenberg
de25ed3f37 mention the '-o -' trick 2009-02-27 13:52:05 +00:00
Daniel Stenberg
40edf25866 217 - Dan Fandrich's "GnuTLS initialization thread safety"
218 - Senthil Raja Velu's "CURLOPT_LOCALPORT option broken", patch by
      Markus Koetter

Both are now committed
2009-02-27 12:11:08 +00:00
Daniel Stenberg
7b7db23633 - 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!
2009-02-27 12:07:14 +00:00
Daniel Stenberg
794b4da840 Indentation fixes, untabify and related whitespace-cleanup. No code changed. 2009-02-27 08:53:10 +00:00
Daniel Stenberg
e9ea3ba4a2 corrected and clarified the top comment 2009-02-25 12:51:39 +00:00
Daniel Stenberg
d207ea1652 - 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.
2009-02-25 12:51:17 +00:00
Daniel Stenberg
625d06ac79 improved 2009-02-24 09:42:39 +00:00
Daniel Stenberg
3460225590 A handy little helper file for doing recursive diffs on curl source/build trees
without involving CVS:

diff -X diff-exclude -ru curl-old curl-patched
2009-02-24 09:35:55 +00:00
Daniel Stenberg
ea6531cf32 - 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.
2009-02-24 08:30:09 +00:00
Daniel Stenberg
2afb88e2ce 4.17 Non-functional connect timeouts 2009-02-23 21:21:00 +00:00
Daniel Stenberg
6c9f37d263 - 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.
2009-02-23 18:45:00 +00:00
Daniel Stenberg
735955282b For 7.19.5 (due to feature freeze)
220 - Take advantage of libssh2_version() that's been added for the upcoming
      1.1, to extract the run-time version number properly.
2009-02-23 16:28:51 +00:00
Yang Tse
dd056e54e2 adjustment for new Mac OS X framework build script 2009-02-23 14:34:40 +00:00
Yang Tse
f5548973ab 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
2009-02-23 12:39:06 +00:00
Daniel Stenberg
07dc741e18 mention default port number 2009-02-23 10:40:36 +00:00
Daniel Stenberg
8b66981ce0 - I renamed everything in the windows builds files that used the name 'curllib'
to the proper 'libcurl' as clearly this caused confusion.
2009-02-23 09:36:54 +00:00
Daniel Stenberg
3a7e8c9f5f lzma compressed tarballs too for some testing, it does produce MUCH smaller
files
2009-02-23 09:36:08 +00:00
Yang Tse
fb90b43432 use the internal snprintf() function 2009-02-23 01:04:18 +00:00
Daniel Stenberg
0302c21253 mention 4 pending fixes/patches 2009-02-20 22:56:55 +00:00
Yang Tse
9182a46233 Mark Incley noticed VS2008 compilation halting when building for Windows 2000 2009-02-20 12:10:23 +00:00
Yang Tse
51b46f451f Do not halt compilation when using VS2008 to build a Windows 2000 target 2009-02-20 11:30:11 +00:00
Daniel Stenberg
11f3690201 clarified the FTP passive/active mode options somewhat 2009-02-20 09:14:25 +00:00
Daniel Stenberg
5784a37f91 the FTP multi interface bug 2009-02-20 08:19:19 +00:00
Daniel Stenberg
af91ff0e06 - 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().
2009-02-20 08:16:03 +00:00
Daniel Stenberg
be3a78f583 The C++ binding home was changed 2009-02-19 18:49:03 +00:00
Daniel Stenberg
7f22da5230 verify that a 550-response for a RETR returns 78 but also that the control
connection is kept alive afterwards
2009-02-19 13:47:06 +00:00
Daniel Stenberg
5af0629ba5 - 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!
2009-02-19 10:36:20 +00:00
Daniel Stenberg
a776e5ad31 spell-fixed comments and other minor non-code edits 2009-02-18 19:31:55 +00:00
Patrick Monnerat
6e422c447a FTP downloads (i.e.: RETR) ending with code 550 now return error CURLE_REMOTE_FILE_NOT_FOUND instead of CURLE_FTP_COULDNT_RETR_FILE. 2009-02-18 11:40:16 +00:00
Patrick Monnerat
4608d0157e Continue sync work on OS400 specific code and RPG binding. 2009-02-17 16:16:07 +00:00
Daniel Stenberg
a24fe59ee4 - Kamil Dudka made NSS-powered builds compile and run again! 2009-02-17 12:18:34 +00:00
Daniel Stenberg
4ad296c60b - 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.
2009-02-17 12:14:41 +00:00
Daniel Stenberg
0517fa153c three new CURLFTP_CREATE_DIR* symbols 2009-02-17 09:43:27 +00:00
Daniel Stenberg
8f81fd6be5 - 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.
2009-02-17 09:07:25 +00:00
Patrick Monnerat
1472be4d3e Preparation of imminent release: synchronizing OS400 wrappers + RPG binding to current state. 2009-02-16 15:33:17 +00:00
Gisle Vanem
8925527fef In MSVC9 'time_t' is a 64-bit quantity. This causes a truncation warning
when an 'int' is assigned to a 'time_t' variable. Hence redefine 'retry_time'
and 'retry_max' to 'time_t'.
2009-02-14 13:43:18 +00:00
Daniel Stenberg
8cdc220bc0 nah, use the simpler year - year range syntax only, no matter what emacs'
copyright-update script thinks
2009-02-14 09:12:55 +00:00
Daniel Stenberg
d315d41a12 - Andre Guibert de Bruet found and fixed a memory leak in the content encoding
code, which could happen on libz errors.
2009-02-14 09:09:09 +00:00
Daniel Stenberg
4f7687895d there is nothing left planned for next release, metalink experiments are post-
poned
2009-02-13 14:34:07 +00:00
Daniel Stenberg
07d46886df Anthony Bryan's letter=>symbol fixes 2009-02-13 09:12:52 +00:00
Yang Tse
b79c8f527f ignore 2009-02-13 06:34:44 +00:00
Yang Tse
0cf10ae4d7 Remove following files generated on previous buildconf run:
ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4
2009-02-13 06:25:35 +00:00
Yang Tse
debe0b561d check for poll() as it is done for other functions 2009-02-13 05:49:58 +00:00
Dan Fandrich
9ddc7ad038 Fixed NTLM on curl-config --features with GnuTLS 2009-02-12 23:57:17 +00:00
Dan Fandrich
9a4c887c4a Added support for Digest and NTLM authentication using GnuTLS. 2009-02-12 20:48:40 +00:00
Daniel Stenberg
de41c6ef43 credit Jocelyn Jaubert for his bug report and associated work 2009-02-12 08:05:23 +00:00
Daniel Stenberg
002cf105c6 - 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)
2009-02-11 21:47:14 +00:00
Daniel Stenberg
fb8fdf9273 Added docs/libcurl/symbols-in-versions 2009-02-10 13:06:25 +00:00
Daniel Stenberg
517b8ed057 completed the CURLPROXY_ collection 2009-02-10 12:52:09 +00:00
Daniel Stenberg
d3d7ed1766 include the symbols-in-versions file in the release archive 2009-02-10 12:39:26 +00:00
Daniel Stenberg
77fd094090 remove a trailing name from a comment 2009-02-10 12:34:41 +00:00
Daniel Stenberg
c65f9acdc7 introducing the symbols-in-versions file, in an effort to help app authors
to better know and track symbols in earlier libcurl versions
2009-02-10 12:33:10 +00:00
Daniel Stenberg
5c4cdcb2d5 mention when CURLOPT_ADDRESS_SCOPE was added 2009-02-10 12:32:12 +00:00
Daniel Stenberg
b1233c7e4d #45. libcurl built to support ipv6 uses getaddrinfo() to resolve host names.
getaddrinfo() sorts the response list

This isn't a libcurl bug since this is how getaddrinfo() is *supposed* to work!
Apparently you deal with this using the /etc/gai.conf file.
2009-02-09 16:09:45 +00:00
Daniel Stenberg
4ebe4b907b #53. SFTP busy-loop problem. should be fixed in 7.19.3 with libssh2 1.0 (or
later)
2009-02-09 16:08:08 +00:00
Daniel Stenberg
bf44d0f640 Moved Curl_strntoupper() to the rawstr.c file where the other raw string
functions are.
2009-02-07 22:53:37 +00:00
Daniel Stenberg
73cf99c052 214 - progress bar prefix, second try (for the curl tool)
patch declined
2009-02-07 22:47:07 +00:00
Dan Fandrich
44c02227e9 Mention the first release of CURLOPT_FTP_FILEMETHOD 2009-02-06 19:25:32 +00:00
Dan Fandrich
77da9a0087 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.
2009-02-05 00:13:40 +00:00
Dan Fandrich
42d2353e74 Fixed a typo (spotted in the FreeBSD ports). 2009-02-04 23:40:57 +00:00
Dan Fandrich
4b441ebac5 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).
2009-02-04 23:33:34 +00:00
Daniel Stenberg
01140217f5 206 - A. Craig West's CURLOPT_HTTP_VERSION change for CONNECT
applied!
2009-02-04 21:22:13 +00:00
Daniel Stenberg
71f3877f3a - 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.
2009-02-03 22:28:41 +00:00
Phil Blundell
83d135f990 * 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.
2009-02-03 14:38:09 +00:00
Daniel Stenberg
d4ac3d53fc - 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!
2009-02-02 21:36:47 +00:00
Daniel Stenberg
f0332c0b58 minor comment fix 2009-02-02 21:20:59 +00:00
Daniel Stenberg
bdd4294e79 - 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.
2009-02-02 16:19:23 +00:00
Daniel Stenberg
dcf92bffd2 - 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 wtih
  this setup since it now parses the "::1 ip6-localhost" line fine in my
  /etc/hosts file!
2009-01-31 20:25:55 +00:00
Daniel Stenberg
a2256e899b - 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.
2009-01-31 20:17:41 +00:00
Daniel Stenberg
8b6805572a - 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!
2009-01-31 18:38:41 +00:00
Daniel Stenberg
607253c2d0 Truly make sure that the vc8 and vc9 makefiles that are generated get included
in the release archive - by using our .dist suffix trick.
2009-01-30 22:32:13 +00:00
Dan Fandrich
09f4a1c5e5 Fixed --disable-proxy for FTP and SOCKS. Thanks to Daniel Egger for reporting
the problem.
2009-01-30 19:29:25 +00:00
Dan Fandrich
5c9fff9c6e Mentioned some other characters that may need escaping on the curl command
line and fixed a few typos.
2009-01-30 18:28:29 +00:00
Yang Tse
99b4912688 ensure that we use the ANSI version functions 2009-01-30 02:35:40 +00:00
Yang Tse
0a6312d66f fix typo in comment 2009-01-30 01:54:22 +00:00
Yang Tse
a97f52db20 Provide another definition missing in MinGW's headers 2009-01-30 01:37:37 +00:00
Yang Tse
5267be57f7 Provide some definitions missing in MinGW's headers 2009-01-29 21:44:36 +00:00
Yang Tse
e813bf31d7 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.
2009-01-29 20:32:27 +00:00
Yang Tse
1bd0be0361 added some more messages to SSPI error function 2009-01-29 15:25:23 +00:00
Yang Tse
996c8ca7c2 Avoid inclusion of ntsecapi.h and directly provide the KERB_WRAP_NO_ENCRYPT
definition to avoid a 'STRING' duplicate definition from OpenSSL's safestack.h
2009-01-29 14:00:18 +00:00
Yang Tse
fec65fbff6 fix compiler warnings 2009-01-29 03:39:10 +00:00
Daniel Stenberg
de4610a55f - 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.
2009-01-28 21:33:58 +00:00
Yang Tse
6e34c2d59a fix compiler warning: conversion from 'int' to 'bool', possible loss of data 2009-01-28 17:43:11 +00:00
Yang Tse
34b09398d5 fix compiler warning: enumerated type mixed with another type 2009-01-28 17:26:26 +00:00
Daniel Stenberg
0516ce7786 - 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.
2009-01-26 22:43:06 +00:00
Daniel Stenberg
bb86462ed7 wrap line at col 80 2009-01-26 14:37:29 +00:00
Daniel Stenberg
8fa8df95fb - 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.
2009-01-26 14:36:18 +00:00
Daniel Stenberg
82ca52713b - 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.
2009-01-26 13:19:03 +00:00
Gunter Knauf
f29e383575 added CURLX_ONES again to object list for dynamic linking. 2009-01-26 07:33:29 +00:00
Daniel Stenberg
5aeef9c1c8 - 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.
2009-01-25 23:26:25 +00:00
Dan Fandrich
ddd3fe5948 Improved the title and keywords 2009-01-21 04:46:13 +00:00
Dan Fandrich
5591550167 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 1092 through 1094 to test various combinations
of ;type= and ;mode= URLs that could potentially fail in the Turkish
locale.
2009-01-21 04:42:47 +00:00
Dan Fandrich
6bb9ef8de4 Call setlocale() for libtest tests to test the effects of locale-induced
libc changes on libcurl.
2009-01-21 04:30:05 +00:00
Daniel Stenberg
14a6788535 - 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).
2009-01-20 06:24:25 +00:00
Daniel Stenberg
6f86826516 fix typo in comment that made it confusing 2009-01-19 19:09:39 +00:00
Daniel Stenberg
0e6ed13454 7.19.3 is out now 2009-01-19 11:50:31 +00:00
Daniel Stenberg
b914f45e9e 700 friendly contributors after the new ones in 7.19.3 were added 2009-01-19 10:25:47 +00:00
Daniel Stenberg
3ed66094e8 17 new contributors from the 7.19.3 release 2009-01-19 10:24:19 +00:00
Daniel Stenberg
718004d9b5 start over on our journey towards 7.19.4... 2009-01-19 10:11:25 +00:00
113 changed files with 5265 additions and 1707 deletions

222
CHANGES
View File

@@ -6,6 +6,228 @@
Changelog 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) Version 7.19.3 (19 January 2009)
Daniel Stenberg (16 Jan 2009) Daniel Stenberg (16 Jan 2009)

49
MacOSX-Framework Executable file
View 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

View File

@@ -27,7 +27,7 @@ ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \ EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \
curl-style.el sample.emacs RELEASE-NOTES buildconf buildconf.bat \ 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 bin_SCRIPTS = curl-config

View File

@@ -1,54 +1,57 @@
Curl and libcurl 7.19.3 Curl and libcurl 7.19.4
Public curl releases: 109 Public curl releases: 110
Command line options: 128 Command line options: 132
curl_easy_setopt() options: 158 curl_easy_setopt() options: 163
Public functions in libcurl: 58 Public functions in libcurl: 58
Known libcurl bindings: 37 Known libcurl bindings: 38
Contributors: 683 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: This release includes the following changes:
o CURLAUTH_DIGEST_IE bit added for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH o Added CURLOPT_NOPROXY and the corresponding --noproxy
o VC9 Makefiles were added to the release package 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: This release includes the following bugfixes:
o build failure when disabling FTP but enabling GSS o missing ssh.obj in VS makefiles
o fixed several calls to memory functions that didn't check return codes o FTP ;type=i URLs now work with CURLOPT_PROXY_TRANSFER_MODE in Turkish
o memory leak for SSL connects with libcurl/NSS when CURLOPT_ISSUERCERT was locale
used o realms with quoted quotation marks in HTTP Digest headers
o re-use of connections with the multi interface when multiple handles used o VC9 makefiles are now really included
the same server o multi interface memory leak with CURLMOPT_MAXCONNECTS set
o memory leak with HTTP GSS/kerberos authentication o CURLINFO_CONTENT_LENGTH_DOWNLOAD size from file:// "transfers" with
o removed the default use of "Pragma: no-cache" CURLOPT_NOBODY set true
o fix SCP/SFTP busyloop by using a new libssh2 1.0 function o memory leak on some libz errors for content encodings
o bad fclose() after a fatal error in cookie code o NSS-enabled build is repaired
o curl_multi_remove_handle() when the handle was in use in a HTTP pipeline o superfluous wait in SFTP downloads removed
o GSS authentication infinite loop problem o FTP with the multi interface no longer kills the control connection as
o 550 response from SIZE no longer treated as missing file easily on transfer failures
o ftps:// control connections now use explicit protection level o compilation halting when using VS2008 to build a Windows 2000 target
o dotted IPv6 addresses longer than 39 bytes failed o ease creation of libcurl Mac OS X Framework
o curl_easy_duphandle() doesn't try to duplicate the connection cache pointer o CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD are -1
o build failure on OS/400 when enabling IPv6 if unknown
o better detection of SFTP failures o Negotiate proxy authentication
o improved connection re-use for subsequent SCP and SFTP transfers o CURLOPT_INTERFACE and CURLOPT_LOCALPORT used together
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
This release includes the following known bugs: 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 This release would not have looked like this without help, code, reports and
advice from friends like these: advice from friends like these:
Yang Tse, Daniel Fandrich, Jim Meyering, Christian Krause, Andreas Wurf, Lisa Xu, Daniel Fandrich, Craig A West, Alexey Borzov, Sharad Gupta,
Markus Koetter, Josef Wolf, Vlad Grachov, Pawel Kierski, Igor Novoseltsev, Peter Sylvester, Chad Monroe, Markus Moeller, Yang Tse, Scott Cantor,
Fred Machado, Ken Hirsch, Keshav Krity, Patrick Monnerat, Mark Karpeles, Patrick Scott, Hidemoto Nakada, Jocelyn Jaubert, Andre Guibert de Bruet,
Anthony Bryan, Peter Korsgaard, Phil Lisiecki, Bas Mevissen, Rob Crittenden, Kamil Dudka, Patrik Thunstrom, Linus Nielsen Feltzing, Mark Incley,
Emil Romanus, Karl Moerder, Daniel Black, Stefan Teleman, Michael Wallner, Daniel Johnson, James Cheng, Brian J. Murrell, Senthil Raja Velu,
Grant Erickson, Tim Ansell, Andrew de los Reyes Markus Koetter, David Kierznowski, Michal Marek
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

@@ -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)
========================= =========================
216 - Markus Moeller's "proxy question" to reverse lookup SOCKS proxys and more
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)
215 - Patch for Metalink Support (for the curl tool) 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 -

View File

@@ -1,5 +1,17 @@
Changelog for the c-ares project 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) * January 14 2009 (Daniel Stenberg)
- ares.h no longer uses the HAVE_STRUCT_IN6_ADDR define check, but instead it - 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 now declares the private struct ares_in6_addr for all systems instead of

View File

@@ -2,8 +2,10 @@ This is what's new and changed in the c-ares 1.6.1 release:
Changed: Changed:
o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is instead o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is
declared and used instead declared and used
p ares_gethostbyname() now supports 'AF_UNSPEC' as a family for resolving
either AF_INET6 or AF_INET
Fixed: Fixed:

View File

@@ -68,17 +68,21 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
*p = 0; *p = 0;
addr.s_addr = inet_addr(line); addr.s_addr = inet_addr(line);
if (addr.s_addr == INADDR_NONE) if (addr.s_addr == INADDR_NONE)
{ {
if (ares_inet_pton(AF_INET6, line, &addr6) > 0) /* It wasn't an AF_INET dotted address, then AF_UNSPEC and AF_INET6
{ families are subject for this further check */
if (family != AF_INET6) if ((family != AF_INET) &&
continue; (ares_inet_pton(AF_INET6, line, &addr6) > 0)) {
addrlen = sizeof(struct in6_addr); addrlen = sizeof(struct in6_addr);
} family = AF_INET6;
else }
continue; else
} continue;
}
else if (family == AF_UNSPEC)
family = AF_INET; /* now confirmed! */
else if (family != AF_INET) else if (family != AF_INET)
/* unknown, keep moving */
continue; continue;
/* Get the canonical hostname. */ /* Get the canonical hostname. */

View File

@@ -61,7 +61,8 @@ struct host_query {
char *name; char *name;
ares_host_callback callback; ares_host_callback callback;
void *arg; 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; const char *remaining_lookups;
int timeouts; int timeouts;
}; };
@@ -71,29 +72,34 @@ static void host_callback(void *arg, int status, int timeouts,
unsigned char *abuf, int alen); unsigned char *abuf, int alen);
static void end_hquery(struct host_query *hquery, int status, static void end_hquery(struct host_query *hquery, int status,
struct hostent *host); struct hostent *host);
static int fake_hostent(const char *name, int family, ares_host_callback callback, static int fake_hostent(const char *name, int family,
void *arg); ares_host_callback callback, void *arg);
static int file_lookup(const char *name, int family, struct hostent **host); static int file_lookup(const char *name, int family, struct hostent **host);
static void sort_addresses(struct hostent *host, const struct apattern *sortlist, static void sort_addresses(struct hostent *host,
int nsort); const struct apattern *sortlist, int nsort);
static void sort6_addresses(struct hostent *host, const struct apattern *sortlist, static void sort6_addresses(struct hostent *host,
int nsort); const struct apattern *sortlist, int nsort);
static int get_address_index(const struct in_addr *addr, const struct apattern *sortlist, static int get_address_index(const struct in_addr *addr,
int nsort); const struct apattern *sortlist, int nsort);
static int get6_address_index(const struct in6_addr *addr, const struct apattern *sortlist, static int get6_address_index(const struct in6_addr *addr,
int nsort); const struct apattern *sortlist, int nsort);
void ares_gethostbyname(ares_channel channel, const char *name, int family, void ares_gethostbyname(ares_channel channel, const char *name, int family,
ares_host_callback callback, void *arg) ares_host_callback callback, void *arg)
{ {
struct host_query *hquery; struct host_query *hquery;
/* Right now we only know how to look up Internet addresses. */ /* Right now we only know how to look up Internet addresses - and unspec
if (family != AF_INET && family != AF_INET6) means try both basically. */
{ switch (family) {
callback(arg, ARES_ENOTIMP, 0, NULL); case AF_INET:
return; case AF_INET6:
} case AF_UNSPEC:
break;
default:
callback(arg, ARES_ENOTIMP, 0, NULL);
return;
}
if (fake_hostent(name, family, callback, arg)) if (fake_hostent(name, family, callback, arg))
return; return;
@@ -107,13 +113,13 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
} }
hquery->channel = channel; hquery->channel = channel;
hquery->name = strdup(name); hquery->name = strdup(name);
hquery->family = family; hquery->want_family = family;
if (!hquery->name) hquery->sent_family = -1; /* nothing is sent yet */
{ if (!hquery->name) {
free(hquery); free(hquery);
callback(arg, ARES_ENOMEM, 0, NULL); callback(arg, ARES_ENOMEM, 0, NULL);
return; return;
} }
hquery->callback = callback; hquery->callback = callback;
hquery->arg = arg; hquery->arg = arg;
hquery->remaining_lookups = channel->lookups; hquery->remaining_lookups = channel->lookups;
@@ -136,17 +142,23 @@ static void next_lookup(struct host_query *hquery, int status_code)
case 'b': case 'b':
/* DNS lookup */ /* DNS lookup */
hquery->remaining_lookups = p + 1; 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, ares_search(hquery->channel, hquery->name, C_IN, T_AAAA,
host_callback, hquery); host_callback, hquery);
else }
else {
hquery->sent_family = AF_INET;
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback, ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
hquery); hquery);
}
return; return;
case 'f': case 'f':
/* Host file lookup */ /* 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, /* this status check below previously checked for !ARES_ENOTFOUND,
but we should not assume that this single error code is the one 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; hquery->timeouts += timeouts;
if (status == ARES_SUCCESS) 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); status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL);
if (host && channel->nsort) if (host && channel->nsort)
sort_addresses(host, channel->sortlist, 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); status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL);
if (status == ARES_ENODATA) if (status == ARES_ENODATA || status == ARES_EBADRESP) {
{ /* The query returned something but either there were no AAAA records (e.g. just CNAME)
/* The query returned something (e.g. CNAME) but there were no or the response was malformed. Try looking up A instead.
AAAA records. Try looking up A instead. */ We should possibly limit this attempt-next logic to AF_UNSPEC lookups only. */
hquery->family = AF_INET; hquery->sent_family = AF_INET;
ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback, ares_search(hquery->channel, hquery->name, C_IN, T_A,
hquery); host_callback, hquery);
return; return;
} }
if (host && channel->nsort) if (host && channel->nsort)
sort6_addresses(host, channel->sortlist, channel->nsort); sort6_addresses(host, channel->sortlist, channel->nsort);
} }
end_hquery(hquery, status, host); 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 */ /* The AAAA query yielded no useful result. Now look up an A instead.
hquery->family = AF_INET; 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, ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
hquery); hquery);
} }

View File

@@ -223,17 +223,33 @@
#define _CRT_NONSTDC_NO_DEPRECATE 1 #define _CRT_NONSTDC_NO_DEPRECATE 1
#endif #endif
/* VS2008 does not support Windows build targets prior to WinXP, */ /* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
/* so, if no build target has been defined we will target WinXP. */ 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) #if defined(_MSC_VER) && (_MSC_VER >= 1500)
# ifndef _WIN32_WINNT # ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501 # define _WIN32_WINNT VS2008_DEFAULT_TARGET
# endif # endif
# ifndef WINVER # ifndef WINVER
# define WINVER 0x0501 # define WINVER VS2008_DEFAULT_TARGET
# endif # endif
# if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501) # if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
# error VS2008 does not support Windows build targets prior to WinXP # error VS2008 does not support Windows build targets prior to Windows 2000
# endif # endif
#endif #endif

5
ares/m4/.cvsignore Normal file
View File

@@ -0,0 +1,5 @@
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4

View File

@@ -277,6 +277,10 @@ for fname in .deps \
libtool \ libtool \
libtool.m4 \ libtool.m4 \
ltmain.sh \ ltmain.sh \
ltoptions.m4 \
ltsugar.m4 \
ltversion.m4 \
lt~obsolete.m4 \
stamp-h1 \ stamp-h1 \
stamp-h2 \ stamp-h2 \
stamp-h3 ; do stamp-h3 ; do

View File

@@ -1171,8 +1171,11 @@ if test X"$OPT_SSL" != Xno; then
PKGTEST="no" PKGTEST="no"
PREFIX_OPENSSL=$OPT_SSL PREFIX_OPENSSL=$OPT_SSL
LIB_OPENSSL="$PREFIX_OPENSSL/lib$libsuff" LIB_OPENSSL="$PREFIX_OPENSSL/lib$libsuff"
LDFLAGS="$LDFLAGS -L$LIB_OPENSSL" if [ "$PREFIX_OPENSSL" != "/usr" ] ; then
CPPFLAGS="$CPPFLAGS -I$PREFIX_OPENSSL/include/openssl -I$PREFIX_OPENSSL/include" LDFLAGS="$LDFLAGS -L$LIB_OPENSSL"
CPPFLAGS="$CPPFLAGS -I$PREFIX_OPENSSL/include"
fi
CPPFLAGS="$CPPFLAGS -I$PREFIX_OPENSSL/include/openssl"
;; ;;
esac esac
@@ -2030,6 +2033,7 @@ CURL_CHECK_FUNC_IOCTL
CURL_CHECK_FUNC_IOCTLSOCKET CURL_CHECK_FUNC_IOCTLSOCKET
CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL
CURL_CHECK_FUNC_LOCALTIME_R CURL_CHECK_FUNC_LOCALTIME_R
CURL_CHECK_FUNC_POLL
CURL_CHECK_FUNC_SETSOCKOPT CURL_CHECK_FUNC_SETSOCKOPT
CURL_CHECK_FUNC_SIGACTION CURL_CHECK_FUNC_SIGACTION
CURL_CHECK_FUNC_SIGINTERRUPT CURL_CHECK_FUNC_SIGINTERRUPT
@@ -2075,7 +2079,6 @@ AC_CHECK_FUNCS([basename \
inet_addr \ inet_addr \
perror \ perror \
pipe \ pipe \
poll \
setlocale \ setlocale \
setmode \ setmode \
setrlimit \ setrlimit \
@@ -2132,45 +2135,6 @@ if test "$ipv6" = "yes"; then
CURL_CHECK_NI_WITHSCOPEID CURL_CHECK_NI_WITHSCOPEID
fi 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 ************************************************************
dnl enable non-blocking communications dnl enable non-blocking communications
dnl dnl
@@ -2505,7 +2469,7 @@ fi
if test "x$USE_WINDOWS_SSPI" = "x1"; then if test "x$USE_WINDOWS_SSPI" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI" SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI"
fi 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" SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
fi fi

40
diff-exclude Normal file
View 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

View File

@@ -32,7 +32,7 @@ C
C++ C++
Written by Jean-Philippe Barrette-LaPierre Written by Jean-Philippe Barrette-LaPierre
http://rrette.com/textpattern/index.php?s=cURLpp http://curlpp.org/
Ch Ch
@@ -54,6 +54,10 @@ Dylan
Written by Chris Double Written by Chris Double
http://dylanlibs.sourceforge.net/ http://dylanlibs.sourceforge.net/
Eiffel
Written by Eiffel Software
http://curl.haxx.se/libcurl/eiffel/
Euphoria Euphoria
Written by Ray Smith Written by Ray Smith

View File

@@ -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.1.2 only the libssl lib is missing
2.2 Does curl work/build with other SSL libraries? 2.2 Does curl work/build with other SSL libraries?
2.3 Where can I find a copy of LIBEAY32.DLL? 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. Usage Problems
3.1 curl: (1) SSL is disabled, https: not supported 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.11 How do I POST with a different Content-Type?
3.12 Why do FTP specific features over HTTP proxy fail? 3.12 Why do FTP specific features over HTTP proxy fail?
3.13 Why does my single/double quotes 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.15 Can I do recursive fetches with curl?
3.16 What certificates do I need when I use SSL? 3.16 What certificates do I need when I use SSL?
3.17 How do I list the root dir of an FTP server? 3.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.14 Redirects work in browser but not with curl!
4.15 FTPS doesn't work 4.15 FTPS doesn't work
4.16 My HTTP POST or PUT requests are slow! 4.16 My HTTP POST or PUT requests are slow!
4.17 Non-functional connect timeouts on Windows
5. libcurl Issues 5. libcurl Issues
5.1 Is libcurl thread-safe? 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.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.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.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. PHP/CURL Issues
7.1 What is PHP/CURL? 7.1 What is PHP/CURL?
@@ -399,7 +400,7 @@ FAQ
accurate and up-to-date pointers to recent OpenSSL DLLs and other binary accurate and up-to-date pointers to recent OpenSSL DLLs and other binary
packages. packages.
2.4 Does curl support Socks (RFC 1928) ? 2.4 Does curl support SOCKS (RFC 1928) ?
Yes, SOCKS 4 and 5 are supported. 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 Remember that curl works and runs on more operating systems than most single
individuals have ever tried. 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 have no built-in support for that, so it will be treated just like any other
contents. contents.
.pac files are a netscape invention and are sometimes used by organizations .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 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 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, the name of the proxy to connect to. Since curl doesn't support Javascript,
it can't support .pac proxy configuration either. 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. 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 - Implement a Javascript interpreter, people have successfully used the
Mozilla javascript engine in the past. Mozilla Javascript engine in the past.
- Ask your admins to stop this, for a static proxy setup or similar. - 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? 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 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 (") 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' curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl'
In Windows, the standard DOS shell treats the %-letter specially and you In Windows, the standard DOS shell treats the %-symbol specially and you
need to use TWO %-letters for each single one you want to use in the URL. 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 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? 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 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 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. not provide NTLM authentication functionality in curl.
NTLM is a Microsoft proprietary protocol. Proprietary formats are evil. You 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 - Meta tags. You can write a HTML tag that will cause the browser to
redirect to another given URL after a certain time. 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. that redirects the browser to another given URL.
There is no way to make curl follow these redirects. You must either 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 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. 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. libcurl Issues
5.1 Is libcurl thread-safe? 5.1 Is libcurl thread-safe?
@@ -897,7 +916,7 @@ FAQ
If you use a OpenSSL-powered libcurl in a multi-threaded environment, you If you use a OpenSSL-powered libcurl in a multi-threaded environment, you
need to provide one or two locking functions: 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 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 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 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. 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 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 the COPYING file) which basically says you have to include the copyright
@@ -1174,7 +1193,7 @@ FAQ
your app. your app.
As can be seen here: http://curl.haxx.se/docs/companies.html and 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. of libcurl and take advantage of it even in commercial environments.

View File

@@ -383,7 +383,7 @@ Win32
- Modify lib/setup.h - Modify lib/setup.h
- Modify lib/Makefile.vc6 - Modify lib/Makefile.vc6
- Add defines to Project/Settings/C/C++/General/Preprocessor Definitions - 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 Important static libcurl usage note

View File

@@ -42,11 +42,6 @@ may have been fixed since this was written!
library header files exporting symbols/macros that should be kept private library header files exporting symbols/macros that should be kept private
to the KfW library. See ticket #5601 at http://krbdev.mit.edu/rt/ 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 52. Gautam Kachroo's issue that identifies a problem with the multi interface
where a connection can be re-used without actually being properly where a connection can be re-used without actually being properly
SSL-negoatiated: 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 function will return prematurely and will confuse the rest of the HTTP
protocol code. This should be very rare. 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. 43. There seems to be a problem when connecting to the Microsoft telnet server.
http://curl.haxx.se/bug/view.cgi?id=1720605 http://curl.haxx.se/bug/view.cgi?id=1720605

View File

@@ -136,6 +136,14 @@ PROXY
curl -U user:passwd -x my-proxy:888 http://www.get.this/ 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. curl also supports SOCKS4 and SOCKS5 proxies with --socks4 and --socks5.
See also the environment variables Curl support that offer further proxy 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 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 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 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 If you want the parameter to contain spaces, you must enclose the entire
parameter within double quotes ("). Within those quotes, you specify a parameter within double quotes ("). Within those quotes, you specify a
@@ -793,8 +801,9 @@ ENVIRONMENT VARIABLES
NO_PROXY NO_PROXY
If a tail substring of the domain-path for a host matches one of these If the host name matches one of these strings, or the host is within the
strings, transactions with that node will not be proxied. 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. The usage of the -x/--proxy flag overrides the environment variables.

View File

@@ -36,6 +36,7 @@ Andreas Ntaflos
Andreas Olsson Andreas Olsson
Andreas Rieke Andreas Rieke
Andreas Schuldei Andreas Schuldei
Andreas Wurf
Andres Garcia Andres Garcia
Andrew Benham Andrew Benham
Andrew Biggs Andrew Biggs
@@ -44,11 +45,13 @@ Andrew Francis
Andrew Fuller Andrew Fuller
Andrew Moise Andrew Moise
Andrew Wansink Andrew Wansink
Andrew de los Reyes
Andr<EFBFBD>s Garc<72>a Andr<EFBFBD>s Garc<72>a
Andy Cedilnik Andy Cedilnik
Andy Serpa Andy Serpa
Andy Tsouladze Andy Tsouladze
Angus Mackay Angus Mackay
Anthony Bryan
Antoine Calando Antoine Calando
Anton Kalmykov Anton Kalmykov
Arkadiusz Miskiewicz Arkadiusz Miskiewicz
@@ -60,6 +63,7 @@ Augustus Saunders
Avery Fay Avery Fay
Axel Tillequin Axel Tillequin
Bart Whiteley Bart Whiteley
Bas Mevissen
Ben Greear Ben Greear
Ben Madsen Ben Madsen
Ben Van Hof Ben Van Hof
@@ -90,6 +94,7 @@ Chris Combes
Chris Flerackers Chris Flerackers
Chris Gaukroger Chris Gaukroger
Chris Maltby Chris Maltby
Christian Krause
Christian Kurz Christian Kurz
Christian Robottom Reis Christian Robottom Reis
Christian Vogt Christian Vogt
@@ -210,6 +215,7 @@ Forrest Cahoon
Frank Hempel Frank Hempel
Frank Keeney Frank Keeney
Frank Ticheler Frank Ticheler
Fred Machado
Fred New Fred New
Fred Noz Fred Noz
Frederic Lepied Frederic Lepied
@@ -235,6 +241,7 @@ Giuseppe Attardi
Giuseppe D'Ambrosio Giuseppe D'Ambrosio
Glen Nakamura Glen Nakamura
Glen Scott Glen Scott
Grant Erickson
Greg Hewgill Greg Hewgill
Greg Morse Greg Morse
Greg Onufer Greg Onufer
@@ -308,6 +315,7 @@ Jes Badwal
Jesper Jensen Jesper Jensen
Jesse Noller Jesse Noller
Jim Drash Jim Drash
Jim Meyering
Joe Halpin Joe Halpin
Joe Malicki Joe Malicki
Joel Chen Joel Chen
@@ -330,6 +338,7 @@ Jonatan Lander
Jonathan Hseu Jonathan Hseu
Jongki Suwandi Jongki Suwandi
Jose Kahan Jose Kahan
Josef Wolf
Josh Kapell Josh Kapell
Juan F. Codagnone Juan F. Codagnone
Juan Ignacio Herv<72>s Juan Ignacio Herv<72>s
@@ -356,6 +365,7 @@ Keith Mok
Ken Hirsch Ken Hirsch
Ken Rastatter Ken Rastatter
Kent Boortz Kent Boortz
Keshav Krity
Kevin Fisk Kevin Fisk
Kevin Lussier Kevin Lussier
Kevin Reed Kevin Reed
@@ -406,6 +416,7 @@ Mario Schroeder
Mark Butler Mark Butler
Mark Davies Mark Davies
Mark Eichin Mark Eichin
Mark Karpeles
Mark Lentczner Mark Lentczner
Markus Koetter Markus Koetter
Markus Moeller Markus Moeller
@@ -496,11 +507,13 @@ Paul Querna
Pavel Cenek Pavel Cenek
Pavel Orehov Pavel Orehov
Pawel A. Gajda Pawel A. Gajda
Pawel Kierski
Pedro Neves Pedro Neves
Pete Su Pete Su
Peter Bray Peter Bray
Peter Forret Peter Forret
Peter Heuchert Peter Heuchert
Peter Korsgaard
Peter Lamberg Peter Lamberg
Peter O'Gorman Peter O'Gorman
Peter Pentchev Peter Pentchev
@@ -513,6 +526,7 @@ Peter Wullinger
Peteris Krumins Peteris Krumins
Phil Blundell Phil Blundell
Phil Karn Phil Karn
Phil Lisiecki
Phil Pellouchoud Phil Pellouchoud
Philip Gladstone Philip Gladstone
Philip Langdale Philip Langdale
@@ -605,6 +619,7 @@ Spiridonoff A.V
Stadler Stephan Stadler Stephan
Stefan Esser Stefan Esser
Stefan Krause Stefan Krause
Stefan Teleman
Stefan Ulrich Stefan Ulrich
Stephan Bergmann Stephan Bergmann
Stephen Collyer Stephen Collyer
@@ -629,6 +644,7 @@ Thomas J. Moore
Thomas Klausner Thomas Klausner
Thomas Schwinge Thomas Schwinge
Thomas Tonino Thomas Tonino
Tim Ansell
Tim Baker Tim Baker
Tim Bartley Tim Bartley
Tim Costello Tim Costello
@@ -666,6 +682,7 @@ Vincent Bronner
Vincent Le Normand Vincent Le Normand
Vincent Penquerc'h Vincent Penquerc'h
Vincent Sanders Vincent Sanders
Vlad Grachov
Vladimir Lazarenko Vladimir Lazarenko
Vojtech Janota Vojtech Janota
Vojtech Minarik Vojtech Minarik

View File

@@ -328,10 +328,10 @@ to provide the data to send.
8.1 Make NTLM work without OpenSSL functions 8.1 Make NTLM work without OpenSSL functions
Get NTLM working using the functions provided by libgcrypt, since GnuTLS Get NTLM working using the functions provided by NSS. Not strictly
already depends on that to function. Not strictly SSL/TLS related, but SSL/TLS related, but hey... Another option is to get available DES and
hey... Another option is to get available DES and MD4 source code from the MD4 source code from the cryptopp library. They are fine license-wise,
cryptopp library. They are fine license-wise, but are C++. but are C++.
8.2 SSL engine stuff 8.2 SSL engine stuff

View File

@@ -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 .\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms .\" * 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 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. 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" .IP "--disable-epsv"
(FTP) Tell curl to disable the use of the EPSV command when doing passive FTP (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, 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 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. 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>" .IP "-D/--dump-header <file>"
Write the protocol headers to the specified file. Write the protocol headers to the specified file.
@@ -421,13 +428,16 @@ compliant than 'nocwd' but without the full penalty of 'multicwd'.
.RE .RE
(Added in 7.15.1) (Added in 7.15.1)
.IP "--ftp-pasv" .IP "--ftp-pasv"
(FTP) Use PASV when transferring. PASV is the internal default behavior, but (FTP) Use passive mode for the data conection. Passive is the internal default
using this option can be used to override a previous --ftp-port option. (Added behavior, but using this option can be used to override a previous
in 7.11.0) \fI-P/-ftp-port\fP option. (Added in 7.11.0)
If this option is used several times, the following occurrences make no 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 difference. Undoing an enforced passive really isn't doable but you must then
instead enforce the correct EPRT again. 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>" .IP "--ftp-alternative-to-user <command>"
(FTP) If authenticating with the USER and PASS commands fails, send this (FTP) If authenticating with the USER and PASS commands fails, send this
command. When connecting to Tumbleweed's Secure Transport server over FTPS 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 Note that this is the negated option name documented. You can thus use
\fI--sessionid\fP to enforce session-ID caching. \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" .IP "--ntlm"
(HTTP) Enables NTLM authentication. The NTLM authentication method was (HTTP) Enables NTLM authentication. The NTLM authentication method was
designed by Microsoft and is used by IIS web servers. It is a proprietary 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. 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 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" .IP "-O/--remote-name"
Write output to a local file named like the remote file we get. (Only the file 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.) 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 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 requests when following a 302 redirection. The non-RFC behaviour is ubiquitous
in web browsers, so curl does the conversion by default to maintain 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 a redirection. This option is meaningful only when using \fI-L/--location\fP
(Added in 7.19.1) (Added in 7.19.1)
.IP "--proxy-anyauth" .IP "--proxy-anyauth"
@@ -896,6 +914,13 @@ with a remote host. (Added in 7.17.1)
.IP "--proxy-ntlm" .IP "--proxy-ntlm"
Tells curl to use HTTP NTLM authentication when communicating with the given Tells curl to use HTTP NTLM authentication when communicating with the given
proxy. Use \fI--ntlm\fP for enabling NTLM with a remote host. 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" .IP "-p/--proxytunnel"
When an HTTP proxy is used (\fI-x/--proxy\fP), this option will cause non-HTTP 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 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. If this option is used several times, the last one will be used.
.IP "-P/--ftp-port <address>" .IP "-P/--ftp-port <address>"
(FTP) Reverses the initiator/listener roles when connecting with FTP. This (FTP) Reverses the default initiator/listener roles when connecting with
switch makes Curl use the PORT command instead of PASV. In practice, PORT FTP. This switch makes curl use active mode. In practice, curl then tells the
tells the server to connect to the client's specified address and port, while server to connect back to the client's specified address and port, while
PASV asks the server for an IP address and port to connect to. <address> passive mode asks the server to setup an IP address and port for it to connect
should be one of: to. <address> should be one of:
.RS .RS
.IP interface .IP interface
i.e "eth0" to specify which interface's IP address you want to use (Unix only) 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 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 was previously wrongly documented and used as --socks without the number
appended.) 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>" .IP "--stderr <file>"
Redirect all writes to stderr to the specified file instead. If the file name 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 is a plain '-', it is instead written to stdout. This option has no point when

View File

@@ -60,8 +60,8 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf curl_easy_init.pdf \
CLEANFILES = $(HTMLPAGES) $(PDFPAGES) 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=. < $< >$@ MAN2HTML= roffit --mandir=. < $< >$@
SUFFIXES = .3 .html SUFFIXES = .3 .html

View File

@@ -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 .\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms .\" * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
.\" * $Id$ .\" * $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 .SH NAME
curl_easy_getinfo - extract information from a curl handle curl_easy_getinfo - extract information from a curl handle
.SH SYNOPSIS .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) data for you. (Added in 7.12.3)
.IP CURLINFO_CONTENT_LENGTH_DOWNLOAD .IP CURLINFO_CONTENT_LENGTH_DOWNLOAD
Pass a pointer to a double to receive the content-length of the download. This 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 .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 .IP CURLINFO_CONTENT_TYPE
Pass a pointer to a 'char *' to receive the content-type of the downloaded 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, 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 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 option is only available in libcurl built with OpenSSL support. (Added in
7.19.1) 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 .SH TIMES
.NF .NF
An overview of the six time values available from curl_easy_getinfo() An overview of the six time values available from curl_easy_getinfo()

View File

@@ -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 .\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms .\" * 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 \fICURLOPT_URL\fP is the only option that \fBmust\fP be set before
\fIcurl_easy_perform(3)\fP is called. \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 .IP CURLOPT_PROXY
Set HTTP proxy to use. The parameter should be a char * to a zero terminated 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 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 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 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. \fICURLOPT_PROXYPORT\fP.
When you tell the library to use an HTTP proxy, libcurl will transparently 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. specified in the proxy string \fICURLOPT_PROXY\fP.
.IP CURLOPT_PROXYTYPE .IP CURLOPT_PROXYTYPE
Pass a long with this option to set type of the proxy. Available options for 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), this are \fICURLPROXY_HTTP\fP, \fICURLPROXY_HTTP_1_0\fP (added in 7.19.4),
\fICURLPROXY_SOCKS5\fP, \fICURLPROXY_SOCKS4A\fP (added in 7.18.0) and \fICURLPROXY_SOCKS4\fP (added in 7.15.2), \fICURLPROXY_SOCKS5\fP,
\fICURLPROXY_SOCKS5_HOSTNAME\fP (added in 7.18.0). The HTTP type is \fICURLPROXY_SOCKS4A\fP (added in 7.18.0) and \fICURLPROXY_SOCKS5_HOSTNAME\fP
default. (Added in 7.10) (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 .IP CURLOPT_HTTPPROXYTUNNEL
Set the parameter to 1 to make the library tunnel all operations through a 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 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 tunnel through it. If you don't know what this means, you probably don't want
this tunneling option. 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 .IP CURLOPT_INTERFACE
Pass a char * as parameter. This sets the interface name to use as outgoing 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 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. overdone.
.IP CURLOPT_ADDRESS_SCOPE .IP CURLOPT_ADDRESS_SCOPE
Pass a long specifying the scope_id value to use when connecting to IPv6 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) .SH NAMES and PASSWORDS OPTIONS (Authentication)
.IP CURLOPT_NETRC .IP CURLOPT_NETRC
This parameter controls the preference of libcurl between using user names and 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 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 returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
libcurl will follow. 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 .IP CURLOPT_UNRESTRICTED_AUTH
A parameter set to 1 tells the library it can continue to send authentication A parameter set to 1 tells the library it can continue to send authentication
(user+password) when following locations, even when hostname changed. This (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, unless another \fICURLOPT_POSTFIELDS\fP or
\fICURLOPT_COPYPOSTFIELDS\fP option is issued. \fICURLOPT_COPYPOSTFIELDS\fP option is issued.
(Added in 7.17.1) (Added in 7.17.1)
.IP CURLOPT_HTTPPOST .IP CURLOPT_HTTPPOST
Tells libcurl you want a multipart/formdata HTTP POST to be made and you 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 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 transfer decoding will be disabled, if set to 1 it is enabled
(default). libcurl does chunked transfer decoding by default unless this (default). libcurl does chunked transfer decoding by default unless this
option is set to zero. (added in 7.16.2) 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 .SH FTP OPTIONS
.IP CURLOPT_FTPPORT .IP CURLOPT_FTPPORT
Pass a pointer to a zero terminated string as parameter. It will be used to 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 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 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) 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 .IP CURLOPT_FTP_RESPONSE_TIMEOUT
Pass a long. Causes curl to set a timeout period (in seconds) on the amount 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 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 file \&"normally" (like in the multicwd case). This is somewhat more standards
compliant than 'nocwd' but without the full penalty of 'multicwd'. compliant than 'nocwd' but without the full penalty of 'multicwd'.
.RE .RE
(Added in 7.15.1)
.SH PROTOCOL OPTIONS .SH PROTOCOL OPTIONS
.IP CURLOPT_TRANSFERTEXT .IP CURLOPT_TRANSFERTEXT
A parameter set to 1 tells the library to use ASCII mode for FTP transfers, 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. 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 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 this feature will have no effect even if the given time condition would not
been met. 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 .IP CURLOPT_TIMEVALUE
Pass a long as parameter. This should be the time in seconds since 1 Jan 1970, 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 and the time will be used in a condition as specified with

View 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

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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); void *userptr);
typedef enum { 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 CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
in 7.10 */ in 7.10 */
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -527,6 +530,17 @@ typedef enum {
CURLFTPAUTH_LAST /* not an option, never use */ CURLFTPAUTH_LAST /* not an option, never use */
} curl_ftpauth; } 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 */ /* parameter for the CURLOPT_FTP_FILEMETHOD option */
typedef enum { typedef enum {
CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
@@ -536,6 +550,21 @@ typedef enum {
CURLFTPMETHOD_LAST /* not an option, never use */ CURLFTPMETHOD_LAST /* not an option, never use */
} curl_ftpmethod; } 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 /* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */ but 32 */
#define CURLOPTTYPE_LONG 0 #define CURLOPTTYPE_LONG 0
@@ -868,7 +897,7 @@ typedef enum {
/* DNS cache timeout */ /* DNS cache timeout */
CINIT(DNS_CACHE_TIMEOUT, LONG, 92), 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), CINIT(PREQUOTE, OBJECTPOINT, 93),
/* set the debug function */ /* set the debug function */
@@ -933,7 +962,10 @@ typedef enum {
argument */ argument */
CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), 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), CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
/* Set this to a bitmask value to enable the particular authentications /* Set this to a bitmask value to enable the particular authentications
@@ -1150,6 +1182,36 @@ typedef enum {
CINIT(PROXYUSERNAME, OBJECTPOINT, 175), CINIT(PROXYUSERNAME, OBJECTPOINT, 175),
CINIT(PROXYPASSWORD, OBJECTPOINT, 176), 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 */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;
@@ -1571,9 +1633,10 @@ typedef enum {
CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
CURLINFO_CERTINFO = CURLINFO_SLIST + 34, CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
/* Fill in new entries below here! */ /* Fill in new entries below here! */
CURLINFO_LASTONE = 34 CURLINFO_LASTONE = 35
} CURLINFO; } CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as

View File

@@ -31,13 +31,13 @@
/* This is the version number of the libcurl package from which this header /* This is the version number of the libcurl package from which this header
file origins: */ 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 /* The numeric version number is also available "in parts" by using these
defines: */ defines: */
#define LIBCURL_VERSION_MAJOR 7 #define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 19 #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 /* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will 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 and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work. 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 * This is the date and time when the full source package was created. The

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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_PROXYUSERPWD || \
(option) == CURLOPT_PROXYUSERNAME || \ (option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYPASSWORD || \ (option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_NOPROXY || \
(option) == CURLOPT_ENCODING || \ (option) == CURLOPT_ENCODING || \
(option) == CURLOPT_REFERER || \ (option) == CURLOPT_REFERER || \
(option) == CURLOPT_USERAGENT || \ (option) == CURLOPT_USERAGENT || \

View File

@@ -7,6 +7,6 @@ Makefile
config.h config.h
stamp-* stamp-*
getdate.c getdate.c
curllib.dsp libcurl.dsp
curllib.vcproj libcurl.vcproj
*.dist *.dist

View File

@@ -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 # This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms # you should have received as part of this distribution. The terms
@@ -22,16 +22,16 @@
########################################################################### ###########################################################################
AUTOMAKE_OPTIONS = foreign nostdinc AUTOMAKE_OPTIONS = foreign nostdinc
DSP = curllib.dsp DSP = libcurl.dsp
VCPROJ = curllib.vcproj VCPROJ = libcurl.vcproj
DOCS = README.encoding README.memoryleak README.ares README.curlx \ DOCS = README.encoding README.memoryleak README.ares README.curlx \
README.hostip README.multi_socket README.httpauth README.pipelining \ README.hostip README.multi_socket README.httpauth README.pipelining \
README.NSS README.curl_off_t README.NSS README.curl_off_t
EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 Makefile.riscos $(DSP) \ 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 \ libcurl.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 \ config.h.in makefile.dj config.dos libcurl.plist \
libcurl.rc config-amigaos.h amigaos.c amigaos.h makefile.amiga \ libcurl.rc config-amigaos.h amigaos.c amigaos.h makefile.amiga \
Makefile.netware nwlib.c nwos.c libcurl.imp msvcproj.head msvcproj.foot \ Makefile.netware nwlib.c nwos.c libcurl.imp msvcproj.head msvcproj.foot \
config-win32ce.h config-os400.h setup-os400.h config-symbian.h \ config-win32ce.h config-os400.h setup-os400.h config-symbian.h \

View File

@@ -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 \ 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 \ 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 \ 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 \ 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 \ 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 \ 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 \ 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 \ 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

View File

@@ -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 # Makefile for building libcurl with MSVC6
# #
@@ -430,6 +450,7 @@ X_OBJS= \
$(DIROBJ)\content_encoding.obj \ $(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \ $(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \ $(DIROBJ)\curl_addrinfo.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\dict.obj \ $(DIROBJ)\dict.obj \
$(DIROBJ)\easy.obj \ $(DIROBJ)\easy.obj \
$(DIROBJ)\escape.obj \ $(DIROBJ)\escape.obj \
@@ -469,8 +490,10 @@ X_OBJS= \
$(DIROBJ)\sendf.obj \ $(DIROBJ)\sendf.obj \
$(DIROBJ)\share.obj \ $(DIROBJ)\share.obj \
$(DIROBJ)\socks.obj \ $(DIROBJ)\socks.obj \
$(DIROBJ)\socks_sspi.obj \
$(DIROBJ)\speedcheck.obj \ $(DIROBJ)\speedcheck.obj \
$(DIROBJ)\splay.obj \ $(DIROBJ)\splay.obj \
$(DIROBJ)\ssh.obj \
$(DIROBJ)\sslgen.obj \ $(DIROBJ)\sslgen.obj \
$(DIROBJ)\ssluse.obj \ $(DIROBJ)\ssluse.obj \
$(DIROBJ)\strequal.obj \ $(DIROBJ)\strequal.obj \

View File

@@ -33,42 +33,39 @@ extern int errno, h_errno;
#include <stabs.h> #include <stabs.h>
void __request(const char *msg); void __request(const char *msg);
#else #else
# define __request( msg ) Printf( msg "\n\a") # define __request( msg ) Printf( msg "\n\a")
#endif #endif
void amiga_cleanup() void amiga_cleanup()
{ {
if(SocketBase) { if(SocketBase) {
CloseLibrary(SocketBase); CloseLibrary(SocketBase);
SocketBase = NULL; SocketBase = NULL;
} }
} }
BOOL amiga_init() BOOL amiga_init()
{ {
if(!SocketBase) if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4); SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) { if(!SocketBase) {
__request("No TCP/IP Stack running!"); __request("No TCP/IP Stack running!");
return FALSE; return FALSE;
} }
if(SocketBaseTags( if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
// SBTM_SETVAL(SBTC_HERRNOLONGPTR), (ULONG) &h_errno, TAG_DONE)) {
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL", __request("SocketBaseTags ERROR");
TAG_DONE)) { return FALSE;
}
__request("SocketBaseTags ERROR");
return FALSE;
}
#ifndef __libnix__ #ifndef __libnix__
atexit(amiga_cleanup); atexit(amiga_cleanup);
#endif #endif
return TRUE; return TRUE;
} }
#ifdef __libnix__ #ifdef __libnix__

View File

@@ -403,22 +403,39 @@
# endif # endif
#endif #endif
/* VS2008 does not support Windows build targets prior to WinXP, */ /* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
/* so, if no build target has been defined we will target WinXP. */ 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) #if defined(_MSC_VER) && (_MSC_VER >= 1500)
# ifndef _WIN32_WINNT # ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501 # define _WIN32_WINNT VS2008_DEFAULT_TARGET
# endif # endif
# ifndef WINVER # ifndef WINVER
# define WINVER 0x0501 # define WINVER VS2008_DEFAULT_TARGET
# endif # endif
# if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501) # if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
# error VS2008 does not support Windows build targets prior to WinXP # error VS2008 does not support Windows build targets prior to Windows 2000
# endif # endif
#endif #endif
/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is quite */ /* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is
/* convoluted, compiler dependant and in some cases even build target dependat. */ quite convoluted, compiler dependant and in some cases even build target
dependant. */
#if defined(HAVE_WS2TCPIP_H) #if defined(HAVE_WS2TCPIP_H)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
# define HAVE_FREEADDRINFO 1 # define HAVE_FREEADDRINFO 1

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -54,8 +54,8 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototype, without it, this crashes */ #include <stdlib.h>
#endif /* on macos 68K */ #endif
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h> #include <sys/filio.h>
@@ -87,6 +87,7 @@
#include "multiif.h" #include "multiif.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "inet_ntop.h" #include "inet_ntop.h"
#include "inet_pton.h"
#include "sslgen.h" /* for Curl_ssl_check_cxn() */ #include "sslgen.h" /* for Curl_ssl_check_cxn() */
/* The last #include file should be: */ /* The last #include file should be: */
@@ -277,12 +278,15 @@ static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd, int af) curl_socket_t sockfd, int af)
{ {
struct SessionHandle *data = conn->data; 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 #ifdef ENABLE_IPV6
struct sockaddr_in6 me6; struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
#endif #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; struct Curl_dns_entry *h=NULL;
unsigned short port = data->set.localport; /* use this port number, 0 for unsigned short port = data->set.localport; /* use this port number, 0 for
"random" */ "random" */
@@ -290,40 +294,64 @@ static CURLcode bindlocal(struct connectdata *conn,
int portnum = data->set.localportrange; int portnum = data->set.localportrange;
const char *dev = data->set.str[STRING_DEVICE]; const char *dev = data->set.str[STRING_DEVICE];
int error; int error;
char myhost[256] = "";
int done = 0; /* -1 for error, 1 for address found */
/************************************************************* /*************************************************************
* Select device to bind socket to * Select device to bind socket to
*************************************************************/ *************************************************************/
if(dev && (strlen(dev)<255) ) { if ( !dev && !port )
char myhost[256] = ""; /* no local kind of binding was requested */
int rc; return CURLE_OK;
bool was_iface = FALSE;
memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
if(dev && (strlen(dev)<255) ) {
/* interface */
if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) { if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) {
/* /*
* We now have the numerical IP address in the 'myhost' buffer * We now have the numerical IP address in the 'myhost' buffer
*/ */
rc = Curl_resolv(conn, myhost, 0, &h); infof(data, "Local Interface %s is ip %s using address family %i\n",
if(rc == CURLRESOLV_PENDING) dev, myhost, af);
(void)Curl_wait_for_resolv(conn, &h); done = 1;
if(h) { #ifdef SO_BINDTODEVICE
was_iface = TRUE; /* 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
} }
else {
if(!was_iface) {
/* /*
* This was not an interface, resolve the name as a host name * This was not an interface, resolve the name as a host name
* or IP number * or IP number
*/ *
/*
* Temporarily force name resolution to use only the address type * Temporarily force name resolution to use only the address type
* of the connection. The resolve functions should really be changed * of the connection. The resolve functions should really be changed
* to take a type parameter instead. * to take a type parameter instead.
*/ */
long ipver = data->set.ip_version; long ipver = data->set.ip_version;
int rc;
if (af == AF_INET) if (af == AF_INET)
data->set.ip_version = CURL_IPRESOLVE_V4; data->set.ip_version = CURL_IPRESOLVE_V4;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
@@ -338,93 +366,66 @@ static CURLcode bindlocal(struct connectdata *conn,
if(h) { if(h) {
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ /* 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) { if(done > 0) {
/* need to fix this #ifdef ENABLE_IPV6
h=Curl_gethost(data, /* ipv6 address */
getmyhost(*myhost,sizeof(myhost)), if((af == AF_INET6) &&
hostent_buf, (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) {
sizeof(hostent_buf)); 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); failf(data, "Couldn't bind to '%s'", dev);
if(h)
Curl_resolv_unlock(data, h);
return CURLE_INTERFACE_FAILED; 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) { else {
/* if a local port number is requested but no local IP, extract the /* no device was given, prepare sa to match af's needs */
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);
}
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
else { /* AF_INET6 */ if ( af == AF_INET6 ) {
memset(&me6, 0, sizeof(me6)); si6->sin6_family = AF_INET6;
me6.sin6_family = AF_INET6; si6->sin6_port = htons(port);
/* in6addr_any isn't always available and since me6 has just been sizeof_sa = sizeof(struct sockaddr_in6);
cleared, it's not strictly necessary to use it here */
/*me6.sin6_addr = in6addr_any;*/
sock = (struct sockaddr *)&me6;
socksize = sizeof(me6);
} }
else
#endif #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 { do {
if( bind(sockfd, sock, sizeof_sa) >= 0) {
/* Set port number to bind to, 0 makes the system pick one */ /* we succeeded to bind */
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 */
struct Curl_sockaddr_storage add; struct Curl_sockaddr_storage add;
socklen_t size = sizeof(add); socklen_t size = sizeof(add);
memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
@@ -432,26 +433,23 @@ static CURLcode bindlocal(struct connectdata *conn,
data->state.os_errno = error = SOCKERRNO; data->state.os_errno = error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s", failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(conn, error)); error, Curl_strerror(conn, error));
if(h)
Curl_resolv_unlock(data, h);
return CURLE_INTERFACE_FAILED; 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); infof(data, "Local port: %d\n", port);
conn->bits.bound = TRUE; conn->bits.bound = TRUE;
if(h)
Curl_resolv_unlock(data, h);
return CURLE_OK; return CURLE_OK;
} }
if(--portnum > 0) { if(--portnum > 0) {
infof(data, "Bind to local port %d failed, trying next\n", port); infof(data, "Bind to local port %d failed, trying next\n", port);
port++; /* try next 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 else
break; break;
@@ -460,8 +458,6 @@ static CURLcode bindlocal(struct connectdata *conn,
data->state.os_errno = error = SOCKERRNO; data->state.os_errno = error = SOCKERRNO;
failf(data, "bind failed with errno %d: %s", failf(data, "bind failed with errno %d: %s",
error, Curl_strerror(conn, error)); error, Curl_strerror(conn, error));
if(h)
Curl_resolv_unlock(data, h);
return CURLE_INTERFACE_FAILED; return CURLE_INTERFACE_FAILED;
} }

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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 /* some servers seem to not generate zlib headers, so this is an attempt
to fix and continue anyway */ 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) { 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->next_in = orig_in;
z->avail_in = nread; z->avail_in = nread;

View File

@@ -91,7 +91,7 @@ struct Cookie *Curl_cookie_add(struct SessionHandle *data,
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data, struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
const char *, struct CookieInfo *, bool); const char *, struct CookieInfo *, bool);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, 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_freelist(struct Cookie *cookies, bool cookiestoo);
void Curl_cookie_clearall(struct CookieInfo *cookies); void Curl_cookie_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies); void Curl_cookie_clearsess(struct CookieInfo *cookies);

119
lib/curl_sspi.c Normal file
View 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
View 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 */

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -111,7 +111,7 @@ static void win32_cleanup(void)
WSACleanup(); WSACleanup();
#endif #endif
#ifdef USE_WINDOWS_SSPI #ifdef USE_WINDOWS_SSPI
Curl_ntlm_global_cleanup(); Curl_sspi_global_cleanup();
#endif #endif
} }
@@ -156,7 +156,7 @@ static CURLcode win32_init(void)
#ifdef USE_WINDOWS_SSPI #ifdef USE_WINDOWS_SSPI
{ {
CURLcode err = Curl_ntlm_global_init(); CURLcode err = Curl_sspi_global_init();
if (err != CURLE_OK) if (err != CURLE_OK)
return err; return err;
} }

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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); tm->tm_sec);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); 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; return result;
} }

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -89,6 +89,7 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h" #include "multiif.h"
#include "url.h" #include "url.h"
#include "rawstr.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -362,6 +363,7 @@ static void ftp_respinit(struct connectdata *conn)
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpc->nread_resp = 0; ftpc->nread_resp = 0;
ftpc->linestart_resp = conn->data->state.buffer; 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 /* 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 */ /* store the latest code for later retrieval */
conn->data->info.httpcode=code; conn->data->info.httpcode=code;
ftpc->pending_resp = FALSE;
return result; 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 */ } /* while there's buffer left and loop is requested */
ftpc->pending_resp = FALSE;
return result; return result;
} }
@@ -814,7 +820,7 @@ static int ftp_getsock(struct connectdata *conn,
/* This is called after the FTP_QUOTE state is passed. /* 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 the correct directory. It may also need to send MKD commands to create
missing ones, if that option is enabled. missing ones, if that option is enabled.
*/ */
@@ -827,7 +833,13 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
/* already done and fine */ /* already done and fine */
result = ftp_state_post_cwd(conn); result = ftp_state_post_cwd(conn);
else { 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) { if(conn->bits.reuse && ftpc->entrypath) {
/* This is a re-used connection. Since we change directory to where the /* 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 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; break;
#endif /* CURL_DISABLE_PROXY */ #endif /* CURL_DISABLE_PROXY */
case CURLPROXY_HTTP: case CURLPROXY_HTTP:
case CURLPROXY_HTTP_1_0:
/* do nothing here. handled later. */ /* do nothing here. handled later. */
break; break;
default: default:
@@ -1900,7 +1913,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
result = CURLE_COULDNT_CONNECT; result = CURLE_COULDNT_CONNECT;
break; break;
} }
#ifndef CURL_DISABLE_HTTP #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY)
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* FIX: this MUST wait for a proper connect first if 'connected' is /* FIX: this MUST wait for a proper connect first if 'connected' is
* FALSE */ * FALSE */
@@ -1926,7 +1939,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
#endif /* CURL_DISABLE_HTTP */ #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
state(conn, FTP_STOP); /* this phase is completed */ 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) { if(data->info.filetime <= data->set.timevalue) {
infof(data, "The requested document is not new enough\n"); infof(data, "The requested document is not new enough\n");
ftp->transfer = FTPTRANSFER_NONE; /* mark this to not transfer data */ ftp->transfer = FTPTRANSFER_NONE; /* mark this to not transfer data */
data->info.timecond = TRUE;
state(conn, FTP_STOP); state(conn, FTP_STOP);
return CURLE_OK; return CURLE_OK;
} }
@@ -2051,6 +2065,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
if(data->info.filetime > data->set.timevalue) { if(data->info.filetime > data->set.timevalue) {
infof(data, "The requested document is not old enough\n"); infof(data, "The requested document is not old enough\n");
ftp->transfer = FTPTRANSFER_NONE; /* mark this to not transfer data */ ftp->transfer = FTPTRANSFER_NONE; /* mark this to not transfer data */
data->info.timecond = TRUE;
state(conn, FTP_STOP); state(conn, FTP_STOP);
return CURLE_OK; return CURLE_OK;
} }
@@ -2295,6 +2310,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
SECONDARYSOCKET, ftp->bytecountp); SECONDARYSOCKET, ftp->bytecountp);
state(conn, FTP_STOP); state(conn, FTP_STOP);
conn->proto.ftpc.pending_resp = TRUE; /* we expect a server response more */
return result; return result;
} }
@@ -2407,6 +2424,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
if(result) if(result)
return result; return result;
conn->proto.ftpc.pending_resp = TRUE; /* we expect a server response more */
state(conn, FTP_STOP); state(conn, FTP_STOP);
} }
else { else {
@@ -2417,7 +2435,8 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
} }
else { else {
failf(data, "RETR response: %03d", ftpcode); 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; break;
case FTP_MKD: case FTP_MKD:
if(ftpcode/100 != 2) { if((ftpcode/100 != 2) && !ftpc->count3--) {
/* failure to MKD the dir */ /* failure to MKD the dir */
failf(data, "Failed to MKD dir: %03d", ftpcode); failf(data, "Failed to MKD dir: %03d", ftpcode);
return CURLE_REMOTE_ACCESS_DENIED; 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 */ 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) { if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* BLOCKING */ /* BLOCKING */
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
@@ -3082,7 +3101,7 @@ static CURLcode ftp_connect(struct connectdata *conn,
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
#endif /* CURL_DISABLE_HTTP */ #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */
if(conn->protocol & PROT_FTPS) { if(conn->protocol & PROT_FTPS) {
/* BLOCKING */ /* BLOCKING */
@@ -3149,6 +3168,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
case CURLE_UPLOAD_FAILED: case CURLE_UPLOAD_FAILED:
case CURLE_REMOTE_ACCESS_DENIED: case CURLE_REMOTE_ACCESS_DENIED:
case CURLE_FILESIZE_EXCEEDED: case CURLE_FILESIZE_EXCEEDED:
case CURLE_REMOTE_FILE_NOT_FOUND:
case CURLE_WRITE_ERROR:
/* the connection stays alive fine even though this happened */ /* the connection stays alive fine even though this happened */
/* fall-through */ /* fall-through */
case CURLE_OK: /* doesn't affect the control connection's status */ 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; 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, * 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 * 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) { if(type) {
*type = 0; /* it was in the middle of the hostname */ *type = 0; /* it was in the middle of the hostname */
command = (char) toupper((int) type[6]); command = Curl_raw_toupper(type[6]);
switch (command) { switch (command) {
case 'A': /* ASCII mode */ case 'A': /* ASCII mode */

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -35,6 +35,7 @@
#include "memory.h" #include "memory.h"
#include "sslgen.h" #include "sslgen.h"
#include "connect.h" /* Curl_getconnectinfo() */ #include "connect.h" /* Curl_getconnectinfo() */
#include "progress.h"
/* Make this the last #include */ /* Make this the last #include */
#include "memdebug.h" #include "memdebug.h"
@@ -167,10 +168,12 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
*param_longp = data->set.ssl.certverifyresult; *param_longp = data->set.ssl.certverifyresult;
break; break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD: 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; break;
case CURLINFO_CONTENT_LENGTH_UPLOAD: 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; break;
case CURLINFO_REDIRECT_TIME: case CURLINFO_REDIRECT_TIME:
*param_doublep = data->progress.t_redirect; *param_doublep = data->progress.t_redirect;
@@ -228,6 +231,10 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
ptr.to_certinfo = &data->info.certs; ptr.to_certinfo = &data->info.certs;
*param_slistp = ptr.to_slist; *param_slistp = ptr.to_slist;
break; break;
case CURLINFO_CONDITION_UNMET:
/* return if the condition prevented the document to get transfered */
*param_longp = data->info.timecond;
break;
default: default:
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -33,6 +33,7 @@
#ifdef USE_GNUTLS #ifdef USE_GNUTLS
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#include <gnutls/x509.h> #include <gnutls/x509.h>
#include <gcrypt.h>
#include <string.h> #include <string.h>
#include <stdlib.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); return sread(s, buf, len);
} }
/* Global GnuTLS init, called from Curl_ssl_init() */ /* Curl_gtls_init()
int Curl_gtls_init(void) *
{ * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
/* Unfortunately we can not init here, things like curl --version will * are not thread-safe and thus this function itself is not thread-safe and
* fail to work if there is no egd socket available because libgcrypt * must only be called from within curl_global_init() to keep the thread
* will EXIT the application!! * situation under control!
* By doing the actual init later (before actually trying to use GnuTLS),
* we can at least provide basic info etc.
*/ */
return 1; int Curl_gtls_init(void)
}
static int _Curl_gtls_init(void)
{ {
int ret = 1; int ret = 1;
if(!gtls_inited) { if(!gtls_inited) {
@@ -180,7 +176,7 @@ static CURLcode handshake(struct connectdata *conn,
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
int rc; int rc;
if(!gtls_inited) if(!gtls_inited)
_Curl_gtls_init(); Curl_gtls_init();
do { do {
rc = gnutls_handshake(session); rc = gnutls_handshake(session);
@@ -271,7 +267,7 @@ Curl_gtls_connect(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
if(!gtls_inited) if(!gtls_inited)
_Curl_gtls_init(); Curl_gtls_init();
/* GnuTLS only supports SSLv3 and TLSv1 */ /* GnuTLS only supports SSLv3 and TLSv1 */
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
@@ -308,8 +304,8 @@ Curl_gtls_connect(struct connectdata *conn,
if(data->set.ssl.CRLfile) { if(data->set.ssl.CRLfile) {
/* set the CRL list file */ /* set the CRL list file */
rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
data->set.ssl.CRLfile, data->set.ssl.CRLfile,
GNUTLS_X509_FMT_PEM); GNUTLS_X509_FMT_PEM);
if(rc < 0) { if(rc < 0) {
failf(data, "error reading crl file %s (%s)\n", failf(data, "error reading crl file %s (%s)\n",
data->set.ssl.CRLfile, gnutls_strerror(rc)); data->set.ssl.CRLfile, gnutls_strerror(rc));
@@ -436,8 +432,8 @@ Curl_gtls_connect(struct connectdata *conn,
if(verify_status & GNUTLS_CERT_INVALID) { if(verify_status & GNUTLS_CERT_INVALID) {
if(data->set.ssl.verifypeer) { if(data->set.ssl.verifypeer) {
failf(data, "server certificate verification failed. CAfile: %s " failf(data, "server certificate verification failed. CAfile: %s "
"CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
return CURLE_SSL_CACERT; return CURLE_SSL_CACERT;
} }
else else
@@ -464,11 +460,11 @@ Curl_gtls_connect(struct connectdata *conn,
unload_file(issuerp); unload_file(issuerp);
if (rc <= 0) { if (rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)", 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; return CURLE_SSL_ISSUER_ERROR;
} }
infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n", 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); 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)); 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 */ #endif /* USE_GNUTLS */

View File

@@ -47,6 +47,7 @@ ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
void Curl_gtls_session_free(void *ptr); void Curl_gtls_session_free(void *ptr);
size_t Curl_gtls_version(char *buffer, size_t size); size_t Curl_gtls_version(char *buffer, size_t size);
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex); int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
int Curl_gtls_seed(struct SessionHandle *data);
/* API setup for GnuTLS */ /* API setup for GnuTLS */
#define curlssl_init Curl_gtls_init #define curlssl_init Curl_gtls_init

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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) { 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: 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; family = PF_INET;
break; break;
case CURL_IPRESOLVE_V6: case CURL_IPRESOLVE_V6:

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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; struct SessionHandle *data = conn->data;
const char *auth=NULL; const char *auth=NULL;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
#ifdef HAVE_GSSAPI
struct negotiatedata *negdata = proxy?
&data->state.proxyneg:&data->state.negotiate;
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
(void)request; (void)request;
@@ -524,14 +528,13 @@ output_auth_headers(struct connectdata *conn,
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) && if((authstatus->picked == CURLAUTH_GSSNEGOTIATE) &&
data->state.negotiate.context && negdata->context && !GSS_ERROR(negdata->status)) {
!GSS_ERROR(data->state.negotiate.status)) {
auth="GSS-Negotiate"; auth="GSS-Negotiate";
result = Curl_output_negotiate(conn, proxy); result = Curl_output_negotiate(conn, proxy);
if(result) if(result)
return result; return result;
authstatus->done = TRUE; authstatus->done = TRUE;
data->state.negotiate.state = GSS_AUTHSENT; negdata->state = GSS_AUTHSENT;
} }
else else
#endif #endif
@@ -1343,6 +1346,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
char *host=(char *)""; char *host=(char *)"";
const char *proxyconn=""; const char *proxyconn="";
const char *useragent=""; const char *useragent="";
const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
"1.0" : "1.1";
if(!checkheaders(data, "Host:")) { if(!checkheaders(data, "Host:")) {
host = aprintf("Host: %s\r\n", host_port); host = aprintf("Host: %s\r\n", host_port);
@@ -1363,12 +1368,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* BLOCKING */ /* BLOCKING */
result = result =
add_bufferf(req_buffer, add_bufferf(req_buffer,
"CONNECT %s:%d HTTP/1.0\r\n" "CONNECT %s:%d HTTP/%s\r\n"
"%s" /* Host: */ "%s" /* Host: */
"%s" /* Proxy-Authorization */ "%s" /* Proxy-Authorization */
"%s" /* User-Agent */ "%s" /* User-Agent */
"%s", /* Proxy-Connection */ "%s", /* Proxy-Connection */
hostname, remote_port, hostname, remote_port, http,
host, host,
conn->allocptr.proxyuserpwd? conn->allocptr.proxyuserpwd?
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)) { if(checkprefix("ftp://", ppath) || checkprefix("ftps://", ppath)) {
char *p = strstr(ppath, ";type="); char *p = strstr(ppath, ";type=");
if(p && p[6] && p[7] == 0) { if(p && p[6] && p[7] == 0) {
switch (toupper((int)((unsigned char)p[6]))) { switch (Curl_raw_toupper(p[6])) {
case 'A': case 'A':
case 'D': case 'D':
case 'I': case 'I':

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -47,6 +47,77 @@
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #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: /* Test example headers:
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598" WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
@@ -90,26 +161,16 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
Curl_digest_cleanup_one(d); Curl_digest_cleanup_one(d);
while(more) { while(more) {
char value[256]; char value[MAX_VALUE_LENGTH];
char content[1024]; char content[MAX_CONTENT_LENGTH];
size_t totlen=0; size_t totlen=0;
while(*header && ISSPACE(*header)) while(*header && ISSPACE(*header))
header++; header++;
/* how big can these strings be? */ /* extract a value=content pair */
if((2 == sscanf(header, "%255[^=]=\"%1023[^\"]\"", if(!get_pair(header, value, content, &header)) {
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;
}
if(Curl_raw_equal(value, "nonce")) { if(Curl_raw_equal(value, "nonce")) {
d->nonce = strdup(content); d->nonce = strdup(content);
if(!d->nonce) if(!d->nonce)
@@ -185,7 +246,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
else else
break; /* we're done here */ break; /* we're done here */
header += totlen;
/* pass all additional spaces here */ /* pass all additional spaces here */
while(*header && ISSPACE(*header)) while(*header && ISSPACE(*header))
header++; header++;
@@ -247,7 +307,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
#ifdef CURL_DOES_CONVERSIONS #ifdef CURL_DOES_CONVERSIONS
CURLcode rc; CURLcode rc;
/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines. /* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
It converts digest text to ASCII so the MD5 will be correct for It converts digest text to ASCII so the MD5 will be correct for
what ultimately goes over the network. what ultimately goes over the network.
*/ */
#define CURL_OUTPUT_DIGEST_CONV(a, b) \ #define CURL_OUTPUT_DIGEST_CONV(a, b) \
@@ -368,7 +428,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
Further details on Digest implementation differences: Further details on Digest implementation differences:
http://www.fngtps.com/2006/09/http-authentication 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, md5this = (unsigned char *)aprintf("%s:%.*s", request,
(int)(tmp - (char *)uripath), uripath); (int)(tmp - (char *)uripath), uripath);
} }

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -60,7 +60,6 @@
#include "http_ntlm.h" #include "http_ntlm.h"
#include "url.h" #include "url.h"
#include "memory.h" #include "memory.h"
#include "ssluse.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -68,9 +67,8 @@
/* "NTLMSSP" signature is always in ASCII regardless of the platform */ /* "NTLMSSP" signature is always in ASCII regardless of the platform */
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
#ifndef USE_WINDOWS_SSPI #ifdef USE_SSLEAY
#include "ssluse.h"
# ifdef USE_SSLEAY
# ifdef USE_OPENSSL # ifdef USE_OPENSSL
# include <openssl/des.h> # include <openssl/des.h>
# include <openssl/md4.h> # include <openssl/md4.h>
@@ -84,9 +82,6 @@
# include <ssl.h> # include <ssl.h>
# include <rand.h> # include <rand.h>
# endif # endif
# else
# error "Can't compile NTLM support without OpenSSL."
# endif
#if OPENSSL_VERSION_NUMBER < 0x00907001L #if OPENSSL_VERSION_NUMBER < 0x00907001L
#define DES_key_schedule des_key_schedule #define DES_key_schedule des_key_schedule
@@ -104,15 +99,20 @@
#define DESKEY(x) &x #define DESKEY(x) &x
#endif #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 #else
# error "Can't compile NTLM support without a crypto library."
#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;
#endif #endif
/* The last #include file should be: */ /* The last #include file should be: */
@@ -319,11 +319,12 @@ CURLntlm Curl_input_ntlm(struct connectdata *conn,
#ifndef USE_WINDOWS_SSPI #ifndef USE_WINDOWS_SSPI
#ifdef USE_SSLEAY
/* /*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set. * 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_key_schedule DESKEYARG(ks))
{ {
DES_cblock key; DES_cblock key;
@@ -340,16 +341,39 @@ static void setup_des_key(unsigned char *key_56,
DES_set_odd_parity(&key); DES_set_odd_parity(&key);
DES_set_key(&key, ks); 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 * 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 * 8 byte plaintext is encrypted with each key and the resulting 24
* bytes are stored in the results array. * bytes are stored in the results array.
*/ */
static void lm_resp(unsigned char *keys, static void lm_resp(const unsigned char *keys,
unsigned char *plaintext, const unsigned char *plaintext,
unsigned char *results) unsigned char *results)
{ {
#ifdef USE_SSLEAY
DES_key_schedule ks; DES_key_schedule ks;
setup_des_key(keys, DESKEY(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)); setup_des_key(keys+14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
DESKEY(ks), DES_ENCRYPT); 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[] = { static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
}; };
unsigned int i; size_t len = CURLMIN(strlen(password), 14);
size_t len = strlen(password);
if(len > 14) Curl_strntoupper((char *)pw, password, len);
len = 14; memset(&pw[len], 0, 14-len);
for (i=0; i<len; i++)
pw[i] = (unsigned char)toupper(password[i]);
for (; i<14; i++)
pw[i] = 0;
#ifdef CURL_DOES_CONVERSIONS #ifdef CURL_DOES_CONVERSIONS
/* /*
@@ -403,6 +438,7 @@ static void mk_lm_hash(struct SessionHandle *data,
{ {
/* Create LanManager hashed password. */ /* Create LanManager hashed password. */
#ifdef USE_SSLEAY
DES_key_schedule ks; DES_key_schedule ks;
setup_des_key(pw, DESKEY(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)); setup_des_key(pw+7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8), DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
DESKEY(ks), DES_ENCRYPT); 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); memset(lmbuffer + 16, 0, 21 - 16);
} }
@@ -455,11 +504,18 @@ static CURLcode mk_nt_hash(struct SessionHandle *data,
{ {
/* Create NT hashed password. */ /* Create NT hashed password. */
#ifdef USE_SSLEAY
MD4_CTX MD4pw; MD4_CTX MD4pw;
MD4_Init(&MD4pw); MD4_Init(&MD4pw);
MD4_Update(&MD4pw, pw, 2*len); MD4_Update(&MD4pw, pw, 2*len);
MD4_Final(ntbuffer, &MD4pw); 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); memset(ntbuffer + 16, 0, 21 - 16);
} }
@@ -559,7 +615,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
#ifdef USE_WINDOWS_SSPI #ifdef USE_WINDOWS_SSPI
if (s_hSecDll == NULL) { if (s_hSecDll == NULL) {
/* not thread safe and leaks - use curl_global_init() to avoid */ /* 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) if (s_hSecDll == NULL)
return err; return err;
} }
@@ -618,7 +674,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ntlm->p_identity = NULL; ntlm->p_identity = NULL;
} }
if(s_pSecFn->AcquireCredentialsHandle( if(s_pSecFn->AcquireCredentialsHandleA(
NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity, NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
NULL, NULL, &ntlm->handle, &tsDummy NULL, NULL, &ntlm->handle, &tsDummy
) != SEC_E_OK) { ) != SEC_E_OK) {
@@ -632,7 +688,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
buf.BufferType = SECBUFFER_TOKEN; buf.BufferType = SECBUFFER_TOKEN;
buf.pvBuffer = ntlmbuf; buf.pvBuffer = ntlmbuf;
status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL, status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
(char *) host, (char *) host,
ISC_REQ_CONFIDENTIALITY | ISC_REQ_CONFIDENTIALITY |
ISC_REQ_REPLAY_DETECT | ISC_REQ_REPLAY_DETECT |
@@ -788,7 +844,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
type_3.pvBuffer = ntlmbuf; type_3.pvBuffer = ntlmbuf;
type_3.cbBuffer = sizeof(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, (char *) host,
ISC_REQ_CONFIDENTIALITY | ISC_REQ_CONFIDENTIALITY |
ISC_REQ_REPLAY_DETECT | ISC_REQ_REPLAY_DETECT |
@@ -849,12 +905,18 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
unsigned char ntbuffer[0x18]; unsigned char ntbuffer[0x18];
unsigned char tmp[0x18]; unsigned char tmp[0x18];
unsigned char md5sum[MD5_DIGEST_LENGTH]; unsigned char md5sum[MD5_DIGEST_LENGTH];
MD5_CTX MD5pw;
unsigned char entropy[8]; unsigned char entropy[8];
/* Need to create 8 bytes random data */ /* 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 */ Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
RAND_bytes(entropy,8); 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 */ /* 8 bytes random data as challenge in lmresp */
memcpy(lmresp,entropy,8); memcpy(lmresp,entropy,8);
@@ -865,9 +927,17 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
memcpy(tmp,&ntlm->nonce[0],8); memcpy(tmp,&ntlm->nonce[0],8);
memcpy(tmp+8,entropy,8); memcpy(tmp+8,entropy,8);
#ifdef USE_SSLEAY
MD5_Init(&MD5pw); MD5_Init(&MD5pw);
MD5_Update(&MD5pw, tmp, 16); MD5_Update(&MD5pw, tmp, 16);
MD5_Final(md5sum, &MD5pw); 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, /* We shall only use the first 8 bytes of md5sum,
but the des code in lm_resp only encrypt the first 8 bytes */ 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) if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
@@ -1110,48 +1180,6 @@ Curl_ntlm_cleanup(struct connectdata *conn)
#endif #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 /* USE_NTLM */
#endif /* !CURL_DISABLE_HTTP */ #endif /* !CURL_DISABLE_HTTP */

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@ typedef enum {
/* this is for ntlm header input */ /* this is for ntlm header input */
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy,
const char *header); const char *header);
/* this is for creating ntlm header output */ /* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); 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) #define Curl_ntlm_cleanup(x)
#endif #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 */ /* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)

View File

@@ -132,15 +132,15 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to,
/* shut gcc up */ /* shut gcc up */
conn = NULL; conn = NULL;
/* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
* libraries modify the input buffer in gss_seal() * libraries modify the input buffer in gss_seal()
*/ */
dec.value = (void*)from; dec.value = (void*)from;
dec.length = length; dec.length = length;
maj = gss_seal(&min, *context, maj = gss_seal(&min, *context,
level == prot_private, level == prot_private,
GSS_C_QOP_DEFAULT, GSS_C_QOP_DEFAULT,
&dec, &state, &enc); &dec, &state, &enc);
if(maj != GSS_S_COMPLETE) if(maj != GSS_S_COMPLETE)
return -1; return -1;
@@ -178,10 +178,12 @@ krb5_auth(void *app_data, struct connectdata *conn)
chan.initiator_addrtype = GSS_C_AF_INET; chan.initiator_addrtype = GSS_C_AF_INET;
chan.initiator_address.length = l - 4; 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_addrtype = GSS_C_AF_INET;
chan.acceptor_address.length = l - 4; 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.length = 0;
chan.application_data.value = NULL; chan.application_data.value = NULL;
@@ -192,12 +194,12 @@ krb5_auth(void *app_data, struct connectdata *conn)
result = Curl_ftpsendf(conn, "AUTH GSSAPI"); result = Curl_ftpsendf(conn, "AUTH GSSAPI");
if(result) if(result)
return -2; return -2;
if(Curl_GetFTPResponse(&nread, conn, NULL)) if(Curl_GetFTPResponse(&nread, conn, NULL))
return -1; return -1;
if(data->state.buffer[0] != '3') if(data->state.buffer[0] != '3')
return -1; return -1;
} }
gssbuf.value = data->state.buffer; gssbuf.value = data->state.buffer;
@@ -206,8 +208,8 @@ krb5_auth(void *app_data, struct connectdata *conn)
if(maj != GSS_S_COMPLETE) { if(maj != GSS_S_COMPLETE) {
gss_release_name(&min, &gssname); gss_release_name(&min, &gssname);
if(service == srv_host) { if(service == srv_host) {
Curl_failf(data, "Error importing service name %s", gssbuf.value); Curl_failf(data, "Error importing service name %s", gssbuf.value);
return AUTH_ERROR; return AUTH_ERROR;
} }
service = srv_host; service = srv_host;
continue; continue;
@@ -224,69 +226,71 @@ krb5_auth(void *app_data, struct connectdata *conn)
do { do {
ret = AUTH_OK; ret = AUTH_OK;
maj = gss_init_sec_context(&min, maj = gss_init_sec_context(&min,
GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
context, context,
gssname, gssname,
GSS_C_NO_OID, GSS_C_NO_OID,
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
0, 0,
&chan, &chan,
gssresp, gssresp,
NULL, NULL,
&gssbuf, &gssbuf,
NULL, NULL,
NULL); NULL);
if(gssresp) { if(gssresp) {
free(_gssresp.value); free(_gssresp.value);
gssresp = NULL; gssresp = NULL;
} }
if(maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) { if(maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
Curl_infof(data, "Error creating security context"); Curl_infof(data, "Error creating security context");
ret = AUTH_ERROR; ret = AUTH_ERROR;
break; break;
} }
if(gssbuf.length != 0) { if(gssbuf.length != 0) {
if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p) < 1) { if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p)
Curl_infof(data, "Out of memory base64-encoding"); < 1) {
ret = AUTH_CONTINUE; Curl_infof(data, "Out of memory base64-encoding");
break; ret = AUTH_CONTINUE;
} break;
}
result = Curl_ftpsendf(conn, "ADAT %s", p); result = Curl_ftpsendf(conn, "ADAT %s", p);
free(p); free(p);
if(result) { if(result) {
ret = -2; ret = -2;
break; break;
} }
if(Curl_GetFTPResponse(&nread, conn, NULL)) { if(Curl_GetFTPResponse(&nread, conn, NULL)) {
ret = -1; ret = -1;
break; break;
} }
if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){ if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
Curl_infof(data, "Server didn't accept auth data\n"); Curl_infof(data, "Server didn't accept auth data\n");
ret = AUTH_ERROR; ret = AUTH_ERROR;
break; break;
} }
p = data->state.buffer + 4; p = data->state.buffer + 4;
p = strstr(p, "ADAT="); p = strstr(p, "ADAT=");
if(p) { if(p) {
_gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)&_gssresp.value); _gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)
if(_gssresp.length < 1) { &_gssresp.value);
Curl_failf(data, "Out of memory base64-encoding"); if(_gssresp.length < 1) {
ret = AUTH_CONTINUE; Curl_failf(data, "Out of memory base64-encoding");
break; ret = AUTH_CONTINUE;
} break;
} }
}
gssresp = &_gssresp; gssresp = &_gssresp;
} }
} while(maj == GSS_S_CONTINUE_NEEDED); } while(maj == GSS_S_CONTINUE_NEEDED);

View File

@@ -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> Package=<5>
{{{ {{{

View File

@@ -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)

View File

@@ -27,6 +27,24 @@
#include <string.h> #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 #ifdef USE_SSLEAY
/* When OpenSSL is available we use the MD5-function from OpenSSL */ /* When OpenSSL is available we use the MD5-function from OpenSSL */
@@ -341,8 +359,6 @@ static void Decode (UINT4 *output,
#endif /* USE_SSLEAY */ #endif /* USE_SSLEAY */
#include "curl_md5.h"
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */ void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
const unsigned char *input) const unsigned char *input)
{ {
@@ -352,4 +368,6 @@ void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
MD5_Final(outbuffer, &ctx); MD5_Final(outbuffer, &ctx);
} }
#endif #endif /* USE_GNUTLS */
#endif /* CURL_DISABLE_CRYPTO_AUTH */

View File

@@ -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 # Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT ** # ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
# TARGTYPE "Win32 (x86) Static Library" 0x0104 # 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 This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run !MESSAGE use the Export Makefile command and run
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "curllib.mak". !MESSAGE NMAKE /f "libcurl.mak".
!MESSAGE !MESSAGE
!MESSAGE You can specify a configuration when running NMAKE !MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 LIB Debug" !MESSAGE NMAKE /f "libcurl.mak" CFG="libcurl - Win32 LIB Debug"
!MESSAGE !MESSAGE
!MESSAGE Possible choices for configuration are: !MESSAGE Possible choices for configuration are:
!MESSAGE !MESSAGE
!MESSAGE "curllib - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "libcurl - Win32 DLL Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "curllib - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "libcurl - Win32 DLL Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "curllib - Win32 LIB Debug" (based on "Win32 (x86) Static Library") !MESSAGE "libcurl - Win32 LIB Debug" (based on "Win32 (x86) Static Library")
!MESSAGE "curllib - Win32 LIB Release" (based on "Win32 (x86) Static Library") !MESSAGE "libcurl - Win32 LIB Release" (based on "Win32 (x86) Static Library")
!MESSAGE !MESSAGE
# Begin Project # Begin Project
@@ -29,7 +29,7 @@ CFG=curllib - Win32 LIB Debug
# PROP Scc_ProjName "" # PROP Scc_ProjName ""
# PROP Scc_LocalPath "" # PROP Scc_LocalPath ""
!IF "$(CFG)" == "curllib - Win32 DLL Debug" !IF "$(CFG)" == "libcurl - Win32 DLL Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # 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 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 # 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_MFC 0
# PROP BASE Use_Debug_Libraries 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 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" # 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_MFC 0
# PROP BASE Use_Debug_Libraries 1 # 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 BASE LIB32 /nologo /out:"LIB-Debug/libcurld.lib" /machine:I386
# ADD 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_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
@@ -141,7 +141,7 @@ LIB32=link.exe -lib
# Begin Target # Begin Target
# Name "curllib - Win32 DLL Debug" # Name "libcurl - Win32 DLL Debug"
# Name "curllib - Win32 DLL Release" # Name "libcurl - Win32 DLL Release"
# Name "curllib - Win32 LIB Debug" # Name "libcurl - Win32 LIB Debug"
# Name "curllib - Win32 LIB Release" # Name "libcurl - Win32 LIB Release"

View File

@@ -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 /* 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 handle around until either A) the connection is closed and killed
properly, or B) another easy_handle uses the connection. properly, or B) another easy_handle uses the connection.
@@ -1237,14 +1237,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break; break;
case CURLM_STATE_WAITPERFORM: 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 */ /* Wait for our turn to PERFORM */
if(!easy->easy_conn->readchannel_inuse && if(!easy->easy_conn->readchannel_inuse &&
isHandleAtHead(easy->easy_handle, isHandleAtHead(easy->easy_handle,
@@ -1254,6 +1246,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(easy, CURLM_STATE_PERFORM); multistate(easy, CURLM_STATE_PERFORM);
result = CURLM_CALL_MULTI_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; break;
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */ 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) { if(easy->result) {
/* The transfer phase returned error, we mark the connection to get /* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is because we can't * closed to prevent being re-used. This is because we can't possibly
* possibly know if the connection is in a good shape or not now. */ * know if the connection is in a good shape or not now. Unless it is
easy->easy_conn->bits.close = TRUE; * a protocol which uses two "channels" like FTP, as then the error
Curl_removeHandleFromPipeline(easy->easy_handle, * happened in the data connection.
easy->easy_conn->recv_pipe); */
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_posttransfer(easy->easy_handle);
Curl_done(&easy->easy_conn, easy->result, FALSE); Curl_done(&easy->easy_conn, easy->result, FALSE);
} }

View File

@@ -455,7 +455,7 @@ static int nss_load_crl(const char* crlfilename, PRBool ascii)
NULL,SEC_CRL_TYPE, NULL,SEC_CRL_TYPE,
NULL,CRL_IMPORT_DEFAULT_OPTIONS, NULL,CRL_IMPORT_DEFAULT_OPTIONS,
NULL,(CRL_DECODE_DEFAULT_OPTIONS| NULL,(CRL_DECODE_DEFAULT_OPTIONS|
CRL_DECODE_DONT_COPY_DER)); CRL_DECODE_DONT_COPY_DER));
if (slot) PK11_FreeSlot(slot); if (slot) PK11_FreeSlot(slot);
if (!crl) return 0; if (!crl) return 0;
SEC_DestroyCrl(crl); SEC_DestroyCrl(crl);
@@ -1140,7 +1140,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
n = strrchr(data->set.str[STRING_CERT], '/'); n = strrchr(data->set.str[STRING_CERT], '/');
if(n) { if(n) {
n++; /* skip last slash */ n++; /* skip last slash */
nickname = aprintf(nickname, "PEM Token #%d:%s", 1, n); nickname = aprintf("PEM Token #%d:%s", 1, n);
if(!nickname) if(!nickname)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@@ -1171,7 +1171,8 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
if(SSL_GetClientAuthDataHook(model, if(SSL_GetClientAuthDataHook(model,
(SSLGetClientAuthData) SelectClientCert, (SSLGetClientAuthData) SelectClientCert,
(void *)connssl) != SECSuccess) { (void *)connssl->client_nickname) !=
SECSuccess) {
curlerr = CURLE_SSL_CERTPROBLEM; curlerr = CURLE_SSL_CERTPROBLEM;
goto error; goto error;
} }

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -25,9 +25,9 @@
#include "rawstr.h" #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. */ its behavior is altered by the current locale. */
static unsigned char my_toupper(unsigned char in) char Curl_raw_toupper(char in)
{ {
switch (in) { switch (in) {
case 'a': 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 * this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
* some further explanation to why this function is necessary. * 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) int Curl_raw_equal(const char *first, const char *second)
{ {
while(*first && *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 */ /* get out of the loop as soon as they don't match */
break; break;
first++; 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 /* 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 loop above is skipped because one of the strings reached zero, we must not
return this as a successful match */ 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) int Curl_raw_nequal(const char *first, const char *second, size_t max)
{ {
while(*first && *second && max) { while(*first && *second && max) {
if(my_toupper(*first) != my_toupper(*second)) { if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
break; break;
} }
max--; max--;
@@ -123,6 +124,20 @@ int Curl_raw_nequal(const char *first, const char *second, size_t max)
if(0 == max) if(0 == max)
return 1; /* they are equal this far */ 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);
}

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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_equal(const char *first, const char *second);
int Curl_raw_nequal(const char *first, const char *second, size_t max); 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 /* checkprefix() is a shorter version of the above, used when the first
argument is zero-byte terminated */ argument is zero-byte terminated */
#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a)) #define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a))
#endif #endif
void Curl_strntoupper(char *dest, const char *src, size_t n);

View File

@@ -455,7 +455,7 @@ int netware_init(void);
#endif #endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM) #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 #define USE_NTLM
#endif #endif
#endif #endif

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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 * This is STUPID BLOCKING behaviour which we frown upon, but right now this
* is what we have... * is what we have...
*/ */
static int blockread_all(struct connectdata *conn, /* connection data */ int Curl_blockread_all(struct connectdata *conn, /* connection data */
curl_socket_t sockfd, /* read from this socket */ curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */ char *buf, /* store read data here */
ssize_t buffersize, /* max amount to read */ ssize_t buffersize, /* max amount to read */
ssize_t *n, /* amount bytes read */ ssize_t *n, /* amount bytes read */
long conn_timeout) /* timeout for data wait long conn_timeout) /* timeout for data wait
relative to relative to
conn->created */ conn->created */
{ {
ssize_t nread; ssize_t nread;
ssize_t allread = 0; ssize_t allread = 0;
@@ -264,7 +264,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
packetsize = 8; /* receive data size */ packetsize = 8; /* receive data size */
/* Receive response */ /* Receive response */
result = blockread_all(conn, sock, (char *)socksreq, packetsize, result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
&actualread, timeout); &actualread, timeout);
if((result != CURLE_OK) || (actualread != packetsize)) { if((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS4 connect request ack."); failf(data, "Failed to receive SOCKS4 connect request ack.");
@@ -429,9 +429,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
} }
socksreq[0] = 5; /* version */ 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[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
socksreq[2] = 0; /* no authentication */ socksreq[2] = 0; /* no authentication */
socksreq[3] = 2; /* username/password */ socksreq[3] = 2; /* username/password */
#endif
Curl_nonblock(sock, FALSE); Curl_nonblock(sock, FALSE);
@@ -462,7 +469,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
Curl_nonblock(sock, FALSE); 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)) { if((result != CURLE_OK) || (actualread != 2)) {
failf(data, "Unable to receive initial SOCKS5 response."); failf(data, "Unable to receive initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
@@ -476,6 +484,15 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
/* Nothing to do, no authentication needed */ /* 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) { else if(socksreq[1] == 2) {
/* Needs user name and password */ /* Needs user name and password */
size_t userlen, pwlen; size_t userlen, pwlen;
@@ -511,7 +528,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread, result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
timeout); timeout);
if((result != CURLE_OK) || (actualread != 2)) { if((result != CURLE_OK) || (actualread != 2)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response."); failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
@@ -529,12 +546,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
} }
else { else {
/* error */ /* error */
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(socksreq[1] == 255) {
#else
if(socksreq[1] == 1) { if(socksreq[1] == 1) {
failf(data, failf(data,
"SOCKS5 GSSAPI per-message authentication is not supported."); "SOCKS5 GSSAPI per-message authentication is not supported.");
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
else if(socksreq[1] == 255) { else if(socksreq[1] == 255) {
#endif
if(!proxy_name || !*proxy_name) { if(!proxy_name || !*proxy_name) {
failf(data, failf(data,
"No authentication method was acceptable. (It is quite likely" "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); *((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); code = Curl_write_plain(conn, sock, (char *)socksreq, packetsize, &written);
if((code != CURLE_OK) || (written != packetsize)) { if((code != CURLE_OK) || (written != packetsize)) {
failf(data, "Failed to send SOCKS5 connect request."); 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 */ 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); &actualread, timeout);
if((result != CURLE_OK) || (actualread != packetsize)) { if((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS5 connect request ack."); 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 */ /* At this point we already read first 10 bytes */
if(packetsize > 10) { #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
packetsize -= 10; if(!conn->socks5_gssapi_enctype) {
result = blockread_all(conn, sock, (char *)&socksreq[10], packetsize, /* decrypt_gssapi_blockread already read the whole packet */
&actualread, timeout); #endif
if((result != CURLE_OK) || (actualread != packetsize)) { if(packetsize > 10) {
failf(data, "Failed to receive SOCKS5 connect request ack."); packetsize -= 10;
return CURLE_COULDNT_CONNECT; 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); Curl_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */ return CURLE_OK; /* Proxy was successful! */

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -23,6 +23,20 @@
* $Id$ * $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 * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
* final destination server. * final destination server.
@@ -45,4 +59,12 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
int sockindex, int sockindex,
struct connectdata *conn); 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
#endif /* __SOCKS_H */

551
lib/socks_gssapi.c Normal file
View 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
View 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

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -21,9 +21,9 @@
* $Id$ * $Id$
***************************************************************************/ ***************************************************************************/
/* This file is for "generic" SSL functions that all libcurl internals should /* This file is for implementing all "generic" SSL functions that all libcurl
use. It is responsible for calling the proper 'ossl' function in ssluse.c internals should use. It is then responsible for calling the proper
(OpenSSL based) or the 'gtls' function in gtls.c (GnuTLS based). "backend" function.
SSL-functions in libcurl should call functions in this source file, and not SSL-functions in libcurl should call functions in this source file, and not
to any specific SSL-layer. to any specific SSL-layer.

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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; break;
} }
if(toupper(c) != toupper(*hostname++)) if(Curl_raw_toupper(c) != Curl_raw_toupper(*hostname++))
break; break;
} }
return HOST_NOMATCH; return HOST_NOMATCH;
@@ -1385,8 +1385,28 @@ ossl_connect_step1(struct connectdata *conn,
enable the bug workaround options if compatibility with somewhat broken enable the bug workaround options if compatibility with somewhat broken
implementations is desired." 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) */ /* disable SSLv2 in the default case (i.e. allow SSLv3 and TLSv1) */
if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT) if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT)

View File

@@ -1124,7 +1124,7 @@ void telrcv(struct connectdata *conn,
/* Escape and send a telnet data block */ /* Escape and send a telnet data block */
/* TODO: write large chunks of data instead of one byte at a time */ /* TODO: write large chunks of data instead of one byte at a time */
static CURLcode send_telnet_data(struct connectdata *conn, static CURLcode send_telnet_data(struct connectdata *conn,
char *buffer, ssize_t nread) char *buffer, ssize_t nread)
{ {
unsigned char outbuf[2]; unsigned char outbuf[2];
ssize_t bytes_written, total_written; 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].fd = conn->sock[FIRSTSOCKET];
pfd[0].events = POLLOUT; pfd[0].events = POLLOUT;
switch (Curl_poll(pfd, 1, -1)) { switch (Curl_poll(pfd, 1, -1)) {
case -1: /* error, abort writing */ case -1: /* error, abort writing */
case 0: /* timeout (will never happen) */ case 0: /* timeout (will never happen) */
rc = CURLE_SEND_ERROR; rc = CURLE_SEND_ERROR;
break; break;
default: /* write! */ default: /* write! */
bytes_written = 0; bytes_written = 0;
rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written, rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written,
out_count-total_written, &bytes_written); out_count-total_written, &bytes_written);
total_written += bytes_written; total_written += bytes_written;
break; break;
} }
/* handle partial write */ /* handle partial write */
} while (rc == CURLE_OK && total_written < out_count); } while (rc == CURLE_OK && total_written < out_count);
@@ -1317,7 +1317,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
while(1) { while(1) {
if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) { if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
keepon = FALSE; keepon = FALSE;
code = CURLE_READ_ERROR; code = CURLE_READ_ERROR;
break; break;
} }
@@ -1327,15 +1327,15 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
&readfile_read, NULL)) { &readfile_read, NULL)) {
keepon = FALSE; keepon = FALSE;
code = CURLE_READ_ERROR; code = CURLE_READ_ERROR;
break; break;
} }
code = send_telnet_data(conn, buf, readfile_read); code = send_telnet_data(conn, buf, readfile_read);
if(code) { if(code) {
keepon = FALSE; keepon = FALSE;
break; 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), if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
&readfile_read, NULL)) { &readfile_read, NULL)) {
keepon = FALSE; keepon = FALSE;
code = CURLE_READ_ERROR; code = CURLE_READ_ERROR;
break; break;
} }
code = send_telnet_data(conn, buf, readfile_read); code = send_telnet_data(conn, buf, readfile_read);
if(code) { if(code) {
keepon = FALSE; keepon = FALSE;
break; break;
} }
} }
break; break;
@@ -1417,10 +1417,10 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
if(pfd[1].revents & POLLIN) { /* read from stdin */ if(pfd[1].revents & POLLIN) { /* read from stdin */
nread = read(0, buf, 255); nread = read(0, buf, 255);
code = send_telnet_data(conn, buf, nread); code = send_telnet_data(conn, buf, nread);
if(code) { if(code) {
keepon = FALSE; keepon = FALSE;
break; break;
} }
} }
if(pfd[0].revents & POLLIN) { if(pfd[0].revents & POLLIN) {

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -26,7 +26,6 @@
#ifndef CURL_DISABLE_TFTP #ifndef CURL_DISABLE_TFTP
/* -- WIN32 approved -- */ /* -- WIN32 approved -- */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
@@ -72,6 +71,7 @@
#include "strerror.h" #include "strerror.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "url.h" #include "url.h"
#include "rawstr.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -82,8 +82,13 @@
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #include "memdebug.h"
/* RFC2348 allows the block size to be negotiated, but we don't support that */ /* RFC2348 allows the block size to be negotiated */
#define TFTP_BLOCKSIZE 512 #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 { typedef enum {
TFTP_MODE_NETASCII=0, TFTP_MODE_NETASCII=0,
@@ -104,6 +109,7 @@ typedef enum {
TFTP_EVENT_DATA = 3, TFTP_EVENT_DATA = 3,
TFTP_EVENT_ACK = 4, TFTP_EVENT_ACK = 4,
TFTP_EVENT_ERROR = 5, TFTP_EVENT_ERROR = 5,
TFTP_EVENT_OACK = 6,
TFTP_EVENT_TIMEOUT TFTP_EVENT_TIMEOUT
} tftp_event_t; } tftp_event_t;
@@ -124,7 +130,7 @@ typedef enum {
} tftp_error_t; } tftp_error_t;
typedef struct tftp_packet { typedef struct tftp_packet {
unsigned char data[2 + 2 + TFTP_BLOCKSIZE]; unsigned char *data;
} tftp_packet_t; } tftp_packet_t;
typedef struct tftp_state_data { typedef struct tftp_state_data {
@@ -134,8 +140,8 @@ typedef struct tftp_state_data {
struct connectdata *conn; struct connectdata *conn;
curl_socket_t sockfd; curl_socket_t sockfd;
int retries; int retries;
int retry_time; time_t retry_time;
int retry_max; time_t retry_max;
time_t start_time; time_t start_time;
time_t max_time; time_t max_time;
unsigned short block; unsigned short block;
@@ -143,7 +149,9 @@ typedef struct tftp_state_data {
struct Curl_sockaddr_storage remote_addr; struct Curl_sockaddr_storage remote_addr;
socklen_t remote_addrlen; socklen_t remote_addrlen;
ssize_t rbytes; ssize_t rbytes;
int sbytes; size_t sbytes;
size_t blksize;
int requested_blksize;
tftp_packet_t rpacket; tftp_packet_t rpacket;
tftp_packet_t spacket; tftp_packet_t spacket;
} tftp_state_data_t; } 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_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_tx(tftp_state_data_t *state, tftp_event_t event) ;
static CURLcode tftp_connect(struct connectdata *conn, bool *done); 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_do(struct connectdata *conn, bool *done);
static CURLcode tftp_done(struct connectdata *conn, static CURLcode tftp_done(struct connectdata *conn,
CURLcode, bool premature); CURLcode, bool premature);
@@ -175,7 +184,7 @@ const struct Curl_handler Curl_handler_tftp = {
ZERO_NULL, /* proto_getsock */ ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */ ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */ ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */ tftp_disconnect, /* disconnect */
PORT_TFTP, /* defport */ PORT_TFTP, /* defport */
PROT_TFTP /* protocol */ PROT_TFTP /* protocol */
}; };
@@ -195,7 +204,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
{ {
time_t maxtime, timeout; time_t maxtime, timeout;
long timeout_ms; long timeout_ms;
const bool start = (state->state == TFTP_STATE_START); bool start = (bool)(state->state == TFTP_STATE_START);
time(&state->start_time); time(&state->start_time);
@@ -256,7 +265,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
state->retry_time=1; state->retry_time=1;
infof(state->conn->data, 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->state, (state->max_time-state->start_time),
state->retry_time, state->retry_max); 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]); 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) static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
{ {
int sbytes; int sbytes;
const char *mode = "octet"; const char *mode = "octet";
char *filename; char *filename;
char buf[8];
struct SessionHandle *data = state->conn->data; struct SessionHandle *data = state->conn->data;
CURLcode res = CURLE_OK; 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 */ /* If we are uploading, send an WRQ */
setpacketevent(&state->spacket, TFTP_EVENT_WRQ); setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
state->conn->data->req.upload_fromhere = state->conn->data->req.upload_fromhere =
(char *)&state->spacket.data[4]; (char *)state->spacket.data+4;
if(data->set.infilesize != -1) if(data->set.infilesize != -1)
Curl_pgrsSetUploadSize(data, data->set.infilesize); 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); setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
} }
/* As RFC3617 describes the separator slash is not actually part of the /* 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, filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
NULL); NULL);
if(!filename) if(!filename)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
snprintf((char *)&state->spacket.data[2], snprintf((char *)state->spacket.data+2,
TFTP_BLOCKSIZE, state->blksize,
"%s%c%s%c", filename, '\0', mode, '\0'); "%s%c%s%c", filename, '\0', mode, '\0');
sbytes = 4 + (int)strlen(filename) + (int)strlen(mode); sbytes = 4 + strlen(filename) + strlen(mode);
sbytes = sendto(state->sockfd, (void *)&state->spacket,
/* 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, sbytes, 0,
state->conn->ip_addr->ai_addr, state->conn->ip_addr->ai_addr,
state->conn->ip_addr->ai_addrlen); 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); Curl_safefree(filename);
break; break;
case TFTP_EVENT_ACK: /* Connected for transmit */ case TFTP_EVENT_OACK:
infof(data, "%s\n", "Connected for transmit"); if(data->set.upload) {
state->state = TFTP_STATE_TX; res = tftp_connect_for_tx(state, event);
res = tftp_set_timeouts(state); }
if(res) else {
break; res = tftp_connect_for_rx(state, event);
return tftp_tx(state, event); }
break;
case TFTP_EVENT_DATA: /* connected for receive */ case TFTP_EVENT_ACK: /* Connected for transmit */
infof(data, "%s\n", "Connected for receive"); res = tftp_connect_for_tx(state, event);
state->state = TFTP_STATE_RX; break;
res = tftp_set_timeouts(state);
if(res) case TFTP_EVENT_DATA: /* Connected for receive */
break; res = tftp_connect_for_rx(state, event);
return tftp_rx(state, event); break;
case TFTP_EVENT_ERROR: case TFTP_EVENT_ERROR:
state->state = TFTP_STATE_FIN; state->state = TFTP_STATE_FIN;
@@ -394,7 +559,6 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
switch(event) { switch(event) {
case TFTP_EVENT_DATA: case TFTP_EVENT_DATA:
/* Is this the block we expect? */ /* Is this the block we expect? */
rblock = getrpacketblock(&state->rpacket); rblock = getrpacketblock(&state->rpacket);
if((state->block+1) != rblock) { 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) */ /* 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; state->state = TFTP_STATE_FIN;
} }
else { else {
@@ -431,6 +595,25 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
} }
break; 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: case TFTP_EVENT_TIMEOUT:
/* Increment the retry count and fail if over the limit */ /* Increment the retry count and fail if over the limit */
state->retries++; state->retries++;
@@ -442,7 +625,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
} }
else { else {
/* Resend the previous ACK */ /* Resend the previous ACK */
sbytes = sendto(state->sockfd, (void *)&state->spacket, sbytes = sendto(state->sockfd, (void *)state->spacket.data,
4, SEND_4TH_ARG, 4, SEND_4TH_ARG,
(struct sockaddr *)&state->remote_addr, (struct sockaddr *)&state->remote_addr,
state->remote_addrlen); state->remote_addrlen);
@@ -518,11 +701,12 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
state->retries = 0; state->retries = 0;
setpacketevent(&state->spacket, TFTP_EVENT_DATA); setpacketevent(&state->spacket, TFTP_EVENT_DATA);
setpacketblock(&state->spacket, state->block); 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; state->state = TFTP_STATE_FIN;
return CURLE_OK; return CURLE_OK;
} }
res = Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes); res = Curl_fillreadbuffer(state->conn, state->blksize,
(int *)&state->sbytes);
if(res) if(res)
return res; return res;
sbytes = sendto(state->sockfd, (void *)state->spacket.data, 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 { else {
/* Re-send the data packet */ /* 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, 4+state->sbytes, SEND_4TH_ARG,
(struct sockaddr *)&state->remote_addr, (struct sockaddr *)&state->remote_addr,
state->remote_addrlen); state->remote_addrlen);
@@ -614,6 +798,26 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
return res; 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; CURLcode code;
tftp_state_data_t *state; 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 /* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */ sessionhandle, deal with it */
Curl_reset_reqproto(conn); Curl_reset_reqproto(conn);
state = conn->data->state.proto.tftp; state = conn->proto.tftpc = calloc(sizeof(tftp_state_data_t), 1);
if(!state) { if(!state)
state = conn->data->state.proto.tftp = calloc(sizeof(tftp_state_data_t), return CURLE_OUT_OF_MEMORY;
1);
if(!state) /* 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; 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->sockfd = state->conn->sock[FIRSTSOCKET];
state->state = TFTP_STATE_START; state->state = TFTP_STATE_START;
state->error = TFTP_ERR_NONE; state->error = TFTP_ERR_NONE;
state->blksize = TFTP_BLKSIZE_DEFAULT;
state->requested_blksize = blksize;
((struct sockaddr *)&state->local_addr)->sa_family = ((struct sockaddr *)&state->local_addr)->sa_family =
(unsigned short)(conn->ip_addr->ai_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); Curl_reset_reqproto(conn);
if(!data->state.proto.tftp) { if(!conn->proto.tftpc) {
code = tftp_connect(conn, done); code = tftp_connect(conn, done);
if(code) if(code)
return 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 */ /* Run the TFTP State Machine */
for(code=tftp_state_machine(state, TFTP_EVENT_INIT); 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 */ /* Wait until ready to read or timeout occurs */
rc=Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, rc=Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD,
state->retry_time * 1000); (int)(state->retry_time * 1000));
if(rc == -1) { if(rc == -1) {
/* bail out */ /* bail out */
@@ -769,8 +994,8 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
/* Receive the packet */ /* Receive the packet */
fromlen = sizeof(fromaddr); fromlen = sizeof(fromaddr);
state->rbytes = (ssize_t)recvfrom(state->sockfd, state->rbytes = (ssize_t)recvfrom(state->sockfd,
(void *)&state->rpacket, (void *)state->rpacket.data,
sizeof(state->rpacket), state->blksize+4,
0, 0,
(struct sockaddr *)&fromaddr, (struct sockaddr *)&fromaddr,
&fromlen); &fromlen);
@@ -796,7 +1021,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
if(state->rbytes > 4 && if(state->rbytes > 4 &&
((state->block+1) == getrpacketblock(&state->rpacket))) { ((state->block+1) == getrpacketblock(&state->rpacket))) {
code = Curl_client_write(conn, CLIENTWRITE_BODY, code = Curl_client_write(conn, CLIENTWRITE_BODY,
(char *)&state->rpacket.data[4], (char *)state->rpacket.data+4,
state->rbytes-4); state->rbytes-4);
if(code) if(code)
return code; return code;
@@ -806,10 +1031,17 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
break; break;
case TFTP_EVENT_ERROR: case TFTP_EVENT_ERROR:
state->error = (tftp_error_t)getrpacketblock(&state->rpacket); 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; break;
case TFTP_EVENT_ACK: case TFTP_EVENT_ACK:
break; 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_RRQ:
case TFTP_EVENT_WRQ: case TFTP_EVENT_WRQ:
default: default:
@@ -904,7 +1136,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
if(type) { if(type) {
*type = 0; /* it was in the middle of the hostname */ *type = 0; /* it was in the middle of the hostname */
command = (char) toupper((int) type[6]); command = Curl_raw_toupper(type[6]);
switch (command) { switch (command) {
case 'A': /* ASCII mode */ case 'A': /* ASCII mode */

File diff suppressed because it is too large Load Diff

338
lib/url.c
View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* 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 */ /* This is our preferred CA cert bundle/path since install time */
#if defined(CURL_CA_BUNDLE) #if defined(CURL_CA_BUNDLE)
res = setstropt(&set->str[STRING_SSL_CAFILE], (char *) 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 * An FTP option that modifies an upload to create missing directories on
* the server. * 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; break;
case CURLOPT_FTP_RESPONSE_TIMEOUT: 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; data->set.ftp_response_timeout = va_arg( param , long ) * 1000;
break; 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: case CURLOPT_DIRLISTONLY:
/* /*
* An option that changes the command to one that asks for a list * 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 /* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */ 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) { if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */ 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 /* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */ 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) { if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */ auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1418,7 +1444,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
case CURLOPT_PROXYTYPE: 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); data->set.proxytype = (curl_proxytype)va_arg(param, long);
break; break;
@@ -1442,6 +1468,23 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break; break;
#endif #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: case CURLOPT_WRITEHEADER:
/* /*
* Custom pointer to pass the header write callback function * 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], result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
va_arg(param, char *)); va_arg(param, char *));
break; break;
case CURLOPT_NOPROXY:
/*
* proxy exception list
*/
result = setstropt(&data->set.str[STRING_NOPROXY],
va_arg(param, char *));
break;
#endif #endif
case CURLOPT_RANGE: case CURLOPT_RANGE:
@@ -2173,6 +2223,22 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.scope = (unsigned int) va_arg(param, long); data->set.scope = (unsigned int) va_arg(param, long);
break; 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: default:
/* unknown tag and its companion, just ignore: */ /* unknown tag and its companion, just ignore: */
result = CURLE_FAILED_INIT; /* correct this */ 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, void Curl_getoff_all_pipelines(struct SessionHandle *data,
struct connectdata *conn) struct connectdata *conn)
{ {
bool recv_head = conn->readchannel_inuse && bool recv_head = (bool)(conn->readchannel_inuse &&
(gethandleathead(conn->recv_pipe) == data); (gethandleathead(conn->recv_pipe) == data));
bool send_head = conn->writechannel_inuse && bool send_head = (bool)(conn->writechannel_inuse &&
(gethandleathead(conn->send_pipe) == data); (gethandleathead(conn->send_pipe) == data));
if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head) if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
conn->readchannel_inuse = FALSE; conn->readchannel_inuse = FALSE;
@@ -2798,6 +2864,7 @@ static CURLcode ConnectPlease(struct SessionHandle *data,
break; break;
#endif /* CURL_DISABLE_PROXY */ #endif /* CURL_DISABLE_PROXY */
case CURLPROXY_HTTP: case CURLPROXY_HTTP:
case CURLPROXY_HTTP_1_0:
/* do nothing here. handled later. */ /* do nothing here. handled later. */
break; break;
default: default:
@@ -3326,7 +3393,19 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,
for (pp = protocols; (p = *pp) != NULL; pp++) for (pp = protocols; (p = *pp) != NULL; pp++)
if(Curl_raw_equal(p->scheme, conn->protostr)) { 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; conn->handler = p;
if(p->setup_connection) { if(p->setup_connection) {
@@ -3353,6 +3432,80 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,
} }
#ifndef CURL_DISABLE_PROXY #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 * Detect what (if any) proxy to use. Remember that this selects a host
* name and is not limited to HTTP proxies only. * 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. * checked if the lowercase versions don't exist.
*/ */
char *no_proxy=NULL; char *no_proxy=NULL;
char *no_proxy_tok_buf;
char proxy_env[128]; char proxy_env[128];
no_proxy=curl_getenv("no_proxy"); no_proxy=curl_getenv("no_proxy");
if(!no_proxy) if(!no_proxy)
no_proxy=curl_getenv("NO_PROXY"); no_proxy=curl_getenv("NO_PROXY");
if(!no_proxy || !Curl_raw_equal("*", no_proxy)) { if(!check_noproxy(conn->host.name, no_proxy)) {
/* NO_PROXY wasn't specified or it wasn't just an asterisk */ /* It was not listed as without proxy */
char *nope; char *protop = conn->protostr;
char *envp = proxy_env;
char *prox;
nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL; /* Now, build <protocol>_proxy and check for such a one to use */
while(nope) { while(*protop)
size_t namelen; *envp++ = (char)tolower((int)*protop++);
char *endptr = strchr(conn->host.name, ':');
if(endptr)
namelen=endptr-conn->host.name;
else
namelen=strlen(conn->host.name);
if(strlen(nope) <= namelen) { /* append _proxy */
char *checkn= strcpy(envp, "_proxy");
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;
/* Now, build <protocol>_proxy and check for such a one to use */ /* read the protocol proxy: */
while(*protop) prox=curl_getenv(proxy_env);
*envp++ = (char)tolower((int)*protop++);
/* append _proxy */ /*
strcpy(envp, "_proxy"); * We don't try the uppercase version of HTTP_PROXY because of
* security reasons:
/* read the protocol proxy: */ *
* 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); prox=curl_getenv(proxy_env);
}
/* if(prox && *prox) { /* don't count "" strings */
* We don't try the uppercase version of HTTP_PROXY because of proxy = prox; /* use this */
* security reasons: }
* else {
* When curl is used in a webserver application proxy = curl_getenv("all_proxy"); /* default proxy to use */
* environment (cgi or php), this environment variable can if(!proxy)
* be controlled by the web server user by setting the proxy=curl_getenv("ALL_PROXY");
* http header 'Proxy:' to some value. }
* } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
* This can cause 'internal' http/ftp requests to be non-proxy */
* 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(no_proxy) if(no_proxy)
free(no_proxy); free(no_proxy);
@@ -3615,7 +3733,8 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]=""; char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
if(data->set.str[STRING_PROXYUSERNAME] != NULL) { 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*/ proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
} }
if(data->set.str[STRING_PROXYPASSWORD] != NULL) { if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
@@ -4103,15 +4222,28 @@ static CURLcode create_conn(struct SessionHandle *data,
and the SessionHandle */ and the SessionHandle */
conn->proxytype = data->set.proxytype; /* type */ 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] && conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] &&
*data->set.str[STRING_PROXY]); *data->set.str[STRING_PROXY]);
conn->bits.httpproxy = (bool)(conn->bits.proxy conn->bits.httpproxy = (bool)(conn->bits.proxy &&
&& (conn->proxytype == CURLPROXY_HTTP)); (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.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_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
@@ -4191,11 +4323,35 @@ static CURLcode create_conn(struct SessionHandle *data,
if(!proxy) if(!proxy)
proxy = detect_proxy(conn); 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) { if(proxy && !*proxy) {
free(proxy); /* Don't bother with an empty proxy string */ free(proxy); /* Don't bother with an empty proxy string */
proxy = NULL; proxy = NULL;
} }
/* proxy must be freed later unless 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 */ #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 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, 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. 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 */ CURLcode res2 = Curl_disconnect(conn); /* close the connection */
/* If we had an error already, make sure we return that one. But /* If we had an error already, make sure we return that one. But

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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); void Curl_reset_reqproto(struct connectdata *conn);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi service */
#endif #endif

View File

@@ -269,13 +269,7 @@ typedef enum {
} curlntlm; } curlntlm;
#ifdef USE_WINDOWS_SSPI #ifdef USE_WINDOWS_SSPI
/* When including these headers, you must define either SECURITY_WIN32 #include "curl_sspi.h"
* or SECURITY_KERNEL, indicating who is compiling the code.
*/
#define SECURITY_WIN32 1
#include <security.h>
#include <sspi.h>
#include <rpc.h>
#endif #endif
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) #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 */ size_t nread_resp; /* number of bytes currently read of a server response */
char *linestart_resp; /* line start pointer for the FTP server response char *linestart_resp; /* line start pointer for the FTP server response
reader function */ 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 count1; /* general purpose counter for the state machine */
int count2; /* 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 long connectindex; /* what index in the connection cache connects index this
particular struct has */ particular struct has */
long protocol; /* PROT_* flags concerning the protocol set */ long protocol; /* PROT_* flags concerning the protocol set */
#define PROT_MISSING (1<<0) #define PROT_HTTP CURLPROTO_HTTP
#define PROT_HTTP (1<<2) #define PROT_HTTPS CURLPROTO_HTTPS
#define PROT_HTTPS (1<<3) #define PROT_FTP CURLPROTO_FTP
#define PROT_FTP (1<<4) #define PROT_TELNET CURLPROTO_TELNET
#define PROT_TELNET (1<<5) #define PROT_DICT CURLPROTO_DICT
#define PROT_DICT (1<<6) #define PROT_LDAP CURLPROTO_LDAP
#define PROT_LDAP (1<<7) #define PROT_FILE CURLPROTO_FILE
#define PROT_FILE (1<<8) #define PROT_FTPS CURLPROTO_FTPS
#define PROT_FTPS (1<<9) #define PROT_TFTP CURLPROTO_TFTP
#define PROT_SSL (1<<10) /* protocol requires SSL */ #define PROT_SCP CURLPROTO_SCP
#define PROT_TFTP (1<<11) #define PROT_SFTP CURLPROTO_SFTP
#define PROT_SCP (1<<12)
#define PROT_SFTP (1<<13) /* 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 #define PROT_CLOSEACTION PROT_FTP /* these ones need action before socket
close */ 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_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 DNS cache and it will not get pruned while locked. It gets unlocked in
@@ -1047,9 +1052,13 @@ struct connectdata {
union { union {
struct ftp_conn ftpc; struct ftp_conn ftpc;
struct ssh_conn sshc; struct ssh_conn sshc;
struct tftp_state_data *tftpc;
} proto; } proto;
int cselect_bits; /* bitmask of socket events */ int cselect_bits; /* bitmask of socket events */
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
int socks5_gssapi_enctype;
#endif
}; };
/* The end of connectdata. */ /* The end of connectdata. */
@@ -1065,6 +1074,8 @@ struct PureInfo {
was unretrievable. We cannot have this of type time_t, was unretrievable. We cannot have this of type time_t,
since time_t is unsigned on several platforms such as since time_t is unsigned on several platforms such as
OpenVMS. */ 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 header_size; /* size of read header(s) in bytes */
long request_size; /* the amount of bytes sent in the request(s) */ long request_size; /* the amount of bytes sent in the request(s) */
long proxyauthavail; /* what proxy auth types were announced */ long proxyauthavail; /* what proxy auth types were announced */
@@ -1288,7 +1299,7 @@ struct UrlState {
struct HTTP *http; struct HTTP *http;
struct HTTP *https; /* alias, just for the sake of being more readable */ struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp; struct FTP *ftp;
void *tftp; /* private for tftp.c-eyes only */ /* void *tftp; not used */
struct FILEPROTO *file; struct FILEPROTO *file;
void *telnet; /* private for telnet.c-eyes only */ void *telnet; /* private for telnet.c-eyes only */
void *generic; void *generic;
@@ -1363,6 +1374,11 @@ enum dupstring {
STRING_PASSWORD, /* <password>, if used */ STRING_PASSWORD, /* <password>, if used */
STRING_PROXYUSERNAME, /* Proxy <username>, if used */ STRING_PROXYUSERNAME, /* Proxy <username>, if used */
STRING_PROXYPASSWORD, /* Proxy <password>, 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 -- */ /* -- end of strings -- */
STRING_LAST /* not used, just an end-of-list marker */ 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 timeout; /* in milliseconds, 0 means no timeout */
long connecttimeout; /* 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 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 */ curl_off_t infilesize; /* size of file to upload, -1 means unknown */
long low_speed_limit; /* bytes/second */ long low_speed_limit; /* bytes/second */
long low_speed_time; /* number of seconds */ 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 */ 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 /* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially this session. They are STATIC, set by libcurl users or at least initially
and they don't change during operations. */ and they don't change during operations. */
@@ -1478,7 +1499,6 @@ struct UserDefined {
bool prefer_ascii; /* ASCII rather than binary */ bool prefer_ascii; /* ASCII rather than binary */
bool ftp_append; /* append, not overwrite, on upload */ bool ftp_append; /* append, not overwrite, on upload */
bool ftp_list_only; /* switch FTP command for listing directories */ 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 ftp_use_port; /* use the FTP PORT command */
bool hide_progress; /* don't use the progress meter */ bool hide_progress; /* don't use the progress meter */
bool http_fail_on_error; /* fail on HTTP error codes >= 300 */ bool http_fail_on_error; /* fail on HTTP error codes >= 300 */
@@ -1520,6 +1540,11 @@ struct UserDefined {
via an HTTP proxy */ via an HTTP proxy */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
unsigned int scope; /* address scope for IPv6 */ 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 { struct Names {

View File

@@ -2,7 +2,7 @@
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="8.00" Version="8.00"
Name="curllib" Name="libcurl"
ProjectGUID="{87EE9DA4-DE1E-4448-8324-183C98DCA588}" ProjectGUID="{87EE9DA4-DE1E-4448-8324-183C98DCA588}"
> >
<Platforms> <Platforms>
@@ -31,9 +31,9 @@
/> />
<Tool Name="VCWebServiceProxyGeneratorTool" <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" <Tool Name="VCManagedResourceCompilerTool"
/> />
@@ -47,7 +47,7 @@
/> />
<Tool Name="VCXDCMakeTool" <Tool Name="VCXDCMakeTool"
/> />
<Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Release/curllib.bsc" <Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Release/libcurl.bsc"
/> />
<Tool Name="VCFxCopTool" <Tool Name="VCFxCopTool"
/> />
@@ -72,9 +72,9 @@
/> />
<Tool Name="VCWebServiceProxyGeneratorTool" <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" <Tool Name="VCManagedResourceCompilerTool"
/> />
@@ -88,7 +88,7 @@
/> />
<Tool Name="VCXDCMakeTool" <Tool Name="VCXDCMakeTool"
/> />
<Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Debug/curllib.bsc" <Tool Name="VCBscMakeTool" SuppressStartupBanner="true" OutputFile=".\Debug/libcurl.bsc"
/> />
<Tool Name="VCFxCopTool" <Tool Name="VCFxCopTool"
/> />

5
m4/.cvsignore Normal file
View File

@@ -0,0 +1,5 @@
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4

View File

@@ -22,7 +22,7 @@
#*************************************************************************** #***************************************************************************
# File version for 'aclocal' use. Keep it a single number. # File version for 'aclocal' use. Keep it a single number.
# serial 43 # serial 45
dnl CURL_INCLUDES_ARPA_INET 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 CURL_INCLUDES_SETJMP
dnl ------------------------------------------------- dnl -------------------------------------------------
dnl Set up variable with list of headers that must be 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 CURL_CHECK_FUNC_SETSOCKOPT
dnl ------------------------------------------------- dnl -------------------------------------------------
dnl Verify if setsockopt is available, prototyped, and dnl Verify if setsockopt is available, prototyped, and

33
maketgz
View File

@@ -1,5 +1,6 @@
#! /bin/sh #! /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: # Replace version number in header file:
sed 's/#define CURL_VERSION .*/#define CURL_VERSION "'$curlversion'"/g' $CHEADER >$CHEADER.dist sed 's/#define CURL_VERSION .*/#define CURL_VERSION "'$curlversion'"/g' $CHEADER >$CHEADER.dist
echo "generate VC8 makefiles" # Generate VC8 and VC9 versions from the VC6 Makefile versions
# Generate VC8 versions from the VC6 Makefile versions for ver in vc8 vc9; do
make -f Makefile.dist vc8 make -f Makefile.dist $ver
mv src/Makefile.$ver src/Makefile.$ver.dist
echo "generate VC9 makefiles" mv lib/Makefile.$ver lib/Makefile.$ver.dist
# Generate VC9 versions from the VC6 Makefile versions done
make -f Makefile.dist vc9
# Replace version number in plist file: # Replace version number in plist file:
PLIST=lib/libcurl.plist PLIST=lib/libcurl.plist
@@ -143,7 +143,16 @@ make -s dist VERSION=$version
bzip2="curl-$version.tar.bz2" bzip2="curl-$version.tar.bz2"
echo "Generating $bzip2" 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 "------------------"
echo "maketgz report:" echo "maketgz report:"
echo "" echo ""
ls -l $targz $bzip2 $zip ls -l $targz $bzip2 $zip $lzma
md5sum $targz $bzip2 $zip
echo "Run this:" 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"

View File

@@ -105,6 +105,8 @@ options:
CURLOPT_PASSWORD CURLOPT_PASSWORD
CURLOPT_PROXYUSERNAME CURLOPT_PROXYUSERNAME
CURLOPT_PROXYPASSWORD CURLOPT_PROXYPASSWORD
CURLOPT_NOPROXY
CURLOPT_SOCKS5_GSSAPI_SERVICE
Else it is the same as for curl_easy_setopt(). Else it is the same as for curl_easy_setopt().
Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the 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. address of an (empty) character buffer, not the address of a string.

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * 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) { if (testwarn) {
testwarn = 0; testwarn = 0;
if ((int) STRING_LAST != (int) STRING_PROXYPASSWORD + 1) if ((int) STRING_LAST != (int) STRING_SOCKS5_GSSAPI_SERVICE + 1)
curl_mfprintf(stderr, curl_mfprintf(stderr,
"*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n"); "*** 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_PASSWORD:
case CURLOPT_PROXYUSERNAME: case CURLOPT_PROXYUSERNAME:
case CURLOPT_PROXYPASSWORD: case CURLOPT_PROXYPASSWORD:
case CURLOPT_NOPROXY:
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
s = va_arg(arg, char *); s = va_arg(arg, char *);
ccsid = va_arg(arg, unsigned int); ccsid = va_arg(arg, unsigned int);

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -131,7 +131,7 @@
d c X'00000010' d c X'00000010'
d CURLAUTH_ANY c X'7FFFFFEF' d CURLAUTH_ANY c X'7FFFFFEF'
d CURLAUTH_ANYSAFE... d CURLAUTH_ANYSAFE...
d c X'7FFFFFEE' ~CURLAUTH_BASIC d c X'7FFFFFEE'
* *
d CURLSSH_AUTH_ANY... d CURLSSH_AUTH_ANY...
d c X'7FFFFFFF' d c X'7FFFFFFF'
@@ -433,6 +433,8 @@
d curl_proxytype s 10i 0 based(######ptr######) Enum d curl_proxytype s 10i 0 based(######ptr######) Enum
d CURLPROXY_HTTP... d CURLPROXY_HTTP...
d c 0 d c 0
d CURLPROXY_HTTP_1_0...
d c 1
d CURLPROXY_SOCKS4... d CURLPROXY_SOCKS4...
d c 4 d c 4
d CURLPROXY_SOCKS5... d CURLPROXY_SOCKS5...
@@ -466,6 +468,15 @@
d CURLFTPAUTH_SSL... d CURLFTPAUTH_SSL...
d c 1 d c 1
d CURLFTPAUTH_TLS... 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 c 2
* *
d curl_ftpmethod s 10i 0 based(######ptr######) Enum d curl_ftpmethod s 10i 0 based(######ptr######) Enum
@@ -792,6 +803,14 @@
d c 10175 d c 10175
d CURLOPT_PROXYPASSWORD... d CURLOPT_PROXYPASSWORD...
d c 10176 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 CURLOPT_POST301...
d c 00161 Obsolescent d c 00161 Obsolescent
@@ -925,6 +944,8 @@
d c X'00300021' d c X'00300021'
d CURLINFO_CERTINFO... CURLINFO_SLIST + 34 d CURLINFO_CERTINFO... CURLINFO_SLIST + 34
d c X'00400022' d c X'00400022'
d CURLINFO_CONDITION_UNMET... CURLINFO_LONG + 35
d c X'00200023'
* *
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
d c X'00200002' d c X'00200002'

View File

@@ -156,7 +156,7 @@ db2_name()
{ {
basename "${1}" | basename "${1}" |
tr '[a-z-]' '[A-Z_]' | tr '[a-z-]' '[A-Z_]' |
sed -e 's/\..*//' \ sed -e 's/\..*//' \
-e 's/^\(..........\).*/\1/' -e 's/^\(..........\).*/\1/'
} }

View File

@@ -13,7 +13,7 @@ cd "${TOPDIR}/lib"
echo '#pragma comment(user, "libcurl version '"${LIBCURL_VERSION}"'")' > os400.c echo '#pragma comment(user, "libcurl version '"${LIBCURL_VERSION}"'")' > os400.c
echo '#pragma comment(date)' >> 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 make_module OS400 os400.c
LINK= # No need to rebuild service program yet. LINK= # No need to rebuild service program yet.
MODULES= MODULES=

View File

@@ -120,8 +120,11 @@ COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
include Makefile.inc include Makefile.inc
curl_OBJECTS := $(patsubst %.c,%.o,$(strip $(CURL_SOURCES))) curl_OBJECTS := $(patsubst %.c,%.o,$(strip $(CURL_SOURCES)))
# curlx_OBJECTS := $(patsubst %.c,%.o,$(notdir $(strip $(CURLX_ONES)))) ifdef DYN
# vpath %.c ../lib curlx_OBJECTS := $(patsubst %.c,%.o,$(notdir $(strip $(CURLX_ONES))))
curl_OBJECTS += $(curlx_OBJECTS)
vpath %.c ../lib
endif
RESOURCE = curl.res RESOURCE = curl.res

View File

@@ -263,22 +263,39 @@
# endif # endif
#endif #endif
/* VS2008 does not support Windows build targets prior to WinXP, */ /* Officially, Microsoft's Windows SDK versions 6.X do not support Windows
/* so, if no build target has been defined we will target WinXP. */ 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) #if defined(_MSC_VER) && (_MSC_VER >= 1500)
# ifndef _WIN32_WINNT # ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501 # define _WIN32_WINNT VS2008_DEFAULT_TARGET
# endif # endif
# ifndef WINVER # ifndef WINVER
# define WINVER 0x0501 # define WINVER VS2008_DEFAULT_TARGET
# endif # endif
# if (_WIN32_WINNT < 0x0501) || (WINVER < 0x0501) # if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET)
# error VS2008 does not support Windows build targets prior to WinXP # error VS2008 does not support Windows build targets prior to Windows 2000
# endif # endif
#endif #endif
/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is quite */ /* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is
/* convoluted, compiler dependant and in some cases even build target dependat. */ quite convoluted, compiler dependant and in some cases even build target
dependant. */
#if defined(HAVE_WS2TCPIP_H) #if defined(HAVE_WS2TCPIP_H)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
# define HAVE_FREEADDRINFO 1 # define HAVE_FREEADDRINFO 1

View File

@@ -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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -448,6 +448,8 @@ struct Configurable {
char *userpwd; char *userpwd;
char *proxyuserpwd; char *proxyuserpwd;
char *proxy; char *proxy;
int proxyver; /* set to CURLPROXY_HTTP* define */
char *noproxy;
bool proxytunnel; bool proxytunnel;
bool ftp_append; /* APPE on ftp */ bool ftp_append; /* APPE on ftp */
bool mute; /* shutup */ bool mute; /* shutup */
@@ -535,6 +537,10 @@ struct Configurable {
char *socksproxy; /* set to server string */ char *socksproxy; /* set to server string */
int socksver; /* set to CURLPROXY_SOCKS* define */ 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; bool tcp_nodelay;
long req_retry; /* number of retries */ long req_retry; /* number of retries */
@@ -772,6 +778,7 @@ static void help(void)
" -N/--no-buffer Disable buffering of the output stream", " -N/--no-buffer Disable buffering of the output stream",
" --no-keepalive Disable keepalive use on the connection", " --no-keepalive Disable keepalive use on the connection",
" --no-sessionid Disable SSL session-ID reusing (SSL)", " --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)", " --ntlm Use HTTP NTLM authentication (H)",
" -o/--output <file> Write output to <file> instead of stdout", " -o/--output <file> Write output to <file> instead of stdout",
" --pass <pass> Pass phrase for the private key (SSL/SSH)", " --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-negotiate Use Negotiate authentication on the proxy (H)",
" --proxy-ntlm Use NTLM authentication on the proxy (H)", " --proxy-ntlm Use NTLM authentication on the proxy (H)",
" -U/--proxy-user <user[:password]> Set proxy user and password", " -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)", " -p/--proxytunnel Operate through a HTTP proxy tunnel (using CONNECT)",
" --pubkey <key> Public key file name (SSH)", " --pubkey <key> Public key file name (SSH)",
" -Q/--quote <cmd> Send command(s) to server before file transfer (F/SFTP)", " -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", " --socks4a <host[:port]> SOCKS4a proxy on given host + port",
" --socks5 <host[:port]> SOCKS5 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", " --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-limit Stop transfer if below speed-limit for 'speed-time' secs",
" -y/--speed-time Time needed to trig speed-limit abort. Defaults to 30", " -y/--speed-time Time needed to trig speed-limit abort. Defaults to 30",
" -2/--sslv2 Use SSLv2 (SSL)", " -2/--sslv2 Use SSLv2 (SSL)",
@@ -1666,6 +1678,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$2", "socks5-hostname", TRUE}, {"$2", "socks5-hostname", TRUE},
{"$3", "keepalive-time", TRUE}, {"$3", "keepalive-time", TRUE},
{"$4", "post302", FALSE}, {"$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}, {"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE}, {"1", "tlsv1", FALSE},
@@ -2175,6 +2193,23 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case '4': /* --post302 */ case '4': /* --post302 */
config->post302 = toggle; config->post302 = toggle;
break; 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; break;
case '#': /* --progress-bar */ case '#': /* --progress-bar */
@@ -2860,6 +2895,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'x': case 'x':
/* proxy */ /* proxy */
GetStr(&config->proxy, nextarg); GetStr(&config->proxy, nextarg);
config->proxyver = CURLPROXY_HTTP;
break; break;
case 'X': case 'X':
/* set custom request */ /* set custom request */
@@ -3641,6 +3677,8 @@ static void free_config_fields(struct Configurable *config)
free(config->proxy); free(config->proxy);
if(config->proxyuserpwd) if(config->proxyuserpwd)
free(config->proxyuserpwd); free(config->proxyuserpwd);
if(config->noproxy)
free(config->noproxy);
if(config->cookie) if(config->cookie)
free(config->cookie); free(config->cookie);
if(config->cookiefile) if(config->cookiefile)
@@ -3691,6 +3729,10 @@ static void free_config_fields(struct Configurable *config)
free(config->referer); free(config->referer);
if (config->hostpubmd5) if (config->hostpubmd5)
free(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->quote); /* checks for config->quote == NULL */
curl_slist_free_all(config->prequote); 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_INFILESIZE_LARGE, uploadfilesize);
my_setopt(curl, CURLOPT_URL, url); /* what to fetch */ my_setopt(curl, CURLOPT_URL, url); /* what to fetch */
my_setopt(curl, CURLOPT_PROXY, config->proxy); /* proxy to use */ 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); my_setopt(curl, CURLOPT_NOPROGRESS, config->noprogress);
if(config->no_body) { if(config->no_body) {
my_setopt(curl, CURLOPT_NOBODY, 1); 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_TRANSFERTEXT, config->use_ascii);
my_setopt(curl, CURLOPT_USERPWD, config->userpwd); my_setopt(curl, CURLOPT_USERPWD, config->userpwd);
my_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); 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_RANGE, config->range);
my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
my_setopt(curl, CURLOPT_TIMEOUT, config->timeout); 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 */ /* new in curl 7.10 */
my_setopt(curl, CURLOPT_ENCODING, 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, my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
config->ftp_create_dirs); config->ftp_create_dirs);
if(config->proxyanyauth) if(config->proxyanyauth)
my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
else if(config->proxynegotiate) 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); 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 */ /* curl 7.13.0 */
my_setopt(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account); 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) { if(retry) {
static const char * const m[]={NULL, static const char * const m[]={
"timeout", NULL, "timeout", "HTTP error", "FTP error"
"HTTP error",
"FTP error"
}; };
warnf(config, "Transient problem: %s " warnf(config, "Transient problem: %s "
"Will retry in %ld seconds. " "Will retry in %ld seconds. "
"%ld retries left.\n", "%ld retries left.\n",
m[retry], m[retry], retry_sleep/1000, retry_numretries);
retry_sleep/1000,
retry_numretries);
go_sleep(retry_sleep); go_sleep(retry_sleep);
retry_numretries--; retry_numretries--;
@@ -4922,15 +4973,13 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
} while(1); } while(1);
if((config->progressmode == CURL_PROGRESS_BAR) && if((config->progressmode == CURL_PROGRESS_BAR) &&
progressbar.calls) { progressbar.calls)
/* if the custom progress bar has been displayed, we output a /* if the custom progress bar has been displayed, we output a
newline here */ newline here */
fputs("\n", progressbar.out); fputs("\n", progressbar.out);
}
if(config->writeout) { if(config->writeout)
ourWriteOut(curl, config->writeout); ourWriteOut(curl, config->writeout);
}
#ifdef USE_ENVIRONMENT #ifdef USE_ENVIRONMENT
if (config->writeenv) if (config->writeenv)
ourWriteEnv(curl); ourWriteEnv(curl);
@@ -5295,12 +5344,14 @@ static char *basename(char *path)
static const char * static const char *
msdosify (const char *file_name) msdosify (const char *file_name)
{ {
static char dos_name[PATH_MAX*2]; static char dos_name[PATH_MAX];
static const char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*"; static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
"|<>\\\":?*"; /* illegal in DOS & W95 */
static const char *illegal_chars_w95 = &illegal_chars_dos[8]; static const char *illegal_chars_w95 = &illegal_chars_dos[8];
int idx, dot_idx; int idx, dot_idx;
const char *s = file_name; const char *s = file_name;
char *d = dos_name; char *d = dos_name;
const char * const dlimit = dos_name + sizeof(dos_name) - 1;
const char *illegal_aliens = illegal_chars_dos; const char *illegal_aliens = illegal_chars_dos;
size_t len = sizeof (illegal_chars_dos) - 1; size_t len = sizeof (illegal_chars_dos) - 1;
int lfn = 0; int lfn = 0;
@@ -5321,7 +5372,7 @@ msdosify (const char *file_name)
*d++ = *s++; *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)) { if (memchr (illegal_aliens, *s, len)) {
/* Dots are special: DOS doesn't allow them as the leading character, /* 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 and a file name cannot have more than a single dot. We leave the

View File

@@ -60,7 +60,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 \ test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 \
test1080 test1081 test1082 test1083 test1084 test1085 test633 test634 \ test1080 test1081 test1082 test1083 test1084 test1085 test633 test634 \
test635 test636 test637 test558 test559 test1086 test1087 test1088 \ test635 test636 test637 test558 test559 test1086 test1087 test1088 \
test1089 test1090 test1089 test1090 test1091 test1092 test1093 test1094 test1095 test1096
filecheck: filecheck:
@mkdir test-place; \ @mkdir test-place; \

View File

@@ -102,12 +102,12 @@ http://test.remote.server.com:1008/path/10080002 --proxy http://%HOSTIP:%HTTPPOR
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/ s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
</strippart> </strippart>
<protocol> <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 Host: test.remote.server.com:1008
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:1008
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

View File

@@ -111,16 +111,16 @@ http://test.remote.server.com:1021/path/10210002 --proxy http://%HOSTIP:%HTTPPOR
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/ s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
</strippart> </strippart>
<protocol> <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 Host: test.remote.server.com:1021
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:1021
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:1021
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

View File

@@ -49,7 +49,7 @@ ftp://test-number:1059/wanted/page -p -x %HOSTIP:%HTTPPORT
^User-Agent:.* ^User-Agent:.*
</strip> </strip>
<protocol> <protocol>
CONNECT test-number:1059 HTTP/1.0 CONNECT test-number:1059 HTTP/1.1
Host: test-number:1059 Host: test-number:1059
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

View File

@@ -884,11 +884,11 @@ http://test.remote.server.com:1060/path/10600002 --proxy http://%HOSTIP:%HTTPPOR
^User-Agent: curl/.* ^User-Agent: curl/.*
</strip> </strip>
<protocol> <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 Host: test.remote.server.com:1060
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:1060
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:1060", response="b527d164630481e2cc48c04d18ed2212" Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:1060", response="b527d164630481e2cc48c04d18ed2212"
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

View File

@@ -889,11 +889,11 @@ http://test.remote.server.com:1061/path/10610002 --proxy http://%HOSTIP:%HTTPPOR
^User-Agent: curl/.* ^User-Agent: curl/.*
</strip> </strip>
<protocol> <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 Host: test.remote.server.com:1061
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:1061
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:1061", response="244a8caab5f343a1a20d2425e4d6e951" Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:1061", response="244a8caab5f343a1a20d2425e4d6e951"
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

View File

@@ -33,10 +33,10 @@ contents
http http
</server> </server>
<name> <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> </name>
<command> <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> </command>
</client> </client>

46
tests/data/test1091 Normal file
View 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
View 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
View 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
View 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
View 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
View 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>

View File

@@ -81,11 +81,11 @@ http://test.remote.server.com:206/path/2060002 --proxy http://%HOSTIP:%HTTPPORT
^User-Agent: curl/.* ^User-Agent: curl/.*
</strip> </strip>
<protocol> <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 Host: test.remote.server.com:206
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:206
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:206", response="5059a96c954981ceb94e17d667c8d3f8" Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.server.com:206", response="5059a96c954981ceb94e17d667c8d3f8"
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

View File

@@ -95,12 +95,12 @@ http://test.remote.server.com:209/path/2090002 --proxy http://%HOSTIP:%HTTPPORT
s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/ s/^(Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA).*/$1/
</strippart> </strippart>
<protocol> <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 Host: test.remote.server.com:209
Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA= Proxy-Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
Proxy-Connection: Keep-Alive 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 Host: test.remote.server.com:209
Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA Proxy-Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAABQAFAHAAAAA
Proxy-Connection: Keep-Alive Proxy-Connection: Keep-Alive

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