Compare commits

..

262 Commits

Author SHA1 Message Date
Daniel Stenberg
f77e89c5d2 RELEASE-NOTES: synced with 92cf6141ed 2013-10-13 23:24:21 +02:00
Daniel Stenberg
92cf6141ed curl: fix --oauth2-bearer in the --help output
After the option rename in 5df04bfafd
2013-10-13 23:21:12 +02:00
Daniel Stenberg
cf12d5b62f OpenSSL: improve the grammar of the language in 39beaa5ffb
Reported-by: Petr Pisar
2013-10-13 23:08:12 +02:00
Andrej E Baranov
39beaa5ffb OpenSSL: use failf() when subjectAltName mismatches
Write to CURLOPT_ERRORBUFFER information about mismatch alternative
certificate subject names.

Signed-off-by: Andrej E Baranov <admin@andrej-andb.ru>
2013-10-13 19:12:58 +02:00
Daniel Stenberg
5df04bfafd curl: rename --bearer to --oauth2-bearer
The option '--bearer' might be slightly ambiguous in name. It doesn't
create any conflict that I am aware of at the moment, however, OAUTH v2
is not the only authentication mechanism which uses "bearer" tokens.

Reported-by: Kyle L. Huff
URL: http://curl.haxx.se/mail/lib-2013-10/0064.html
2013-10-12 23:26:38 +02:00
Kamil Dudka
d015f4ccac ssh: improve the logic for detecting blocking direction
This fixes a regression introduced by commit 0feeab78 limiting the speed
of SCP upload to 16384 B/s on a fast connection (such as localhost).
2013-10-12 23:03:28 +02:00
Dan Fandrich
143d7c13d8 Fixed typo in Makefile.inc that left http2.h out of the tar ball 2013-10-12 21:09:17 +02:00
Heinrich Schaefer
9b33ecfd01 minor fix in doc 2013-10-11 11:57:26 +02:00
Gisle Vanem
ca1b34b887 curl_setup_once: fix errno access for lwip on Windows
lib/curl_setup_once.h assumed lwIP on Windows uses 'SetLastError()' to
set network errors. It doesn't; it uses 'errno'.
2013-10-09 14:45:42 +02:00
Daniel Stenberg
f0f95c97f7 test1239: verify 4cd444e01a and the simulated 304 response 2013-10-07 14:42:21 +02:00
Derek Higgins
4cd444e01a HTTP: Output http response 304 when modified time is too old
When using the -w '%{http_code}' flag and simulating a Not Modified then
304 should be output.
2013-10-07 14:16:39 +02:00
Daniel Stenberg
8264478490 contributors: helper script to dig out contributors from git 2013-10-07 09:47:03 +02:00
Daniel Stenberg
b46491900d RELEASE-NOTES: add twos refs to bug reports 2013-10-07 00:10:59 +02:00
Daniel Stenberg
725288bf2f RELEASE-NOTES: synced with 173160c0d0 2013-10-06 23:36:21 +02:00
Nick Zitzmann
173160c0d0 darwinssl: block TLS_RSA_WITH_NULL_SHA256 cipher
Credit (for catching a cipher I forgot to add to the blocked ciphers list):
https://www.ssllabs.com/ssltest/viewMyClient.html
2013-10-02 21:19:28 -05:00
Daniel Stenberg
3c3622b662 OpenSSL: acknowledge CURLOPT_SSL_VERIFYHOST without VERIFYPEER
Setting only CURLOPT_SSL_VERIFYHOST without CURLOPT_SSL_VERIFYPEER set
should still verify that the host name fields in the server certificate
is fine or return failure.

Bug: http://curl.haxx.se/mail/lib-2013-10/0002.html
Reported-by: Ishan SinghLevett
2013-10-02 15:40:02 +02:00
Daniel Stenberg
a22c478ed7 KNOWN_BUGS: #84: CURLINFO_SSL_VERIFYRESULT
CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
backends and not for any other!
2013-10-02 15:39:47 +02:00
François Charlier
3d43a48781 xattr: add support for FreeBSD xattr API 2013-10-01 22:53:47 +02:00
Daniel Stenberg
c8b05b809e curl_easy_setopt.3: slight clarification of SEEKFUNCTION 2013-09-30 14:58:06 +02:00
Steve Holme
ca995010d0 tests: Fixed typos from commit 25a0c96a49 2013-09-29 20:32:23 +01:00
Steve Holme
25a0c96a49 tests: Updated email addresses in SMTP tests following recent changes 2013-09-29 16:48:02 +01:00
Steve Holme
a8b606b1a6 test909: Removed custom EHLO response after recent changes
...as it is no longer required following capability and authentication
changes and is now causing problems following commit 49341628b5 as
the test number is obtained from the client address in the EHLO.
2013-09-29 16:25:11 +01:00
Steve Holme
20a99a45c0 ftpserver.pl: Fixed compilation error from commit 49341628b5 2013-09-29 13:13:13 +01:00
Steve Holme
49341628b5 ftpserver.pl: Moved specifying the test number from the RCPT address
...to the client address as this frees the RCPT strings to contain
just an email address and by passing the test number into curl as the
client address remains consistent with POP3 and IMAP tests as they are
specified in the URL.
2013-09-29 10:02:00 +01:00
Steve Holme
ab7e6afd44 ftpserver.pl: Added unwanted argument check to SMTP DATA command handler 2013-09-29 09:25:23 +01:00
Daniel Stenberg
4d7bf73fc3 getinmemory: remove a comment
The comment mentioned the need to free the data, but the example already
does that free
2013-09-29 00:16:21 +02:00
Daniel Stenberg
3c34f453fa postinmemory: new example
This is similar to getinmemory.c but with an initial POST.

Combined-by: Ulf Samuelsson
2013-09-29 00:12:30 +02:00
Daniel Stenberg
d5f687ed8f win32: fix Visual Studio 2010 build with WINVER >= 0x600
If no WINVER and/or _WIN32_IWNNT define was set, the Windows platform
SDK often defaults to high value, e.g. 0x601 (whoch may probably depend
on the Windows version being used, in my case Windows 7).

If WINVER >= 0x600 then winsock2.h includes some defines for WSAPoll(),
e.g. POLLIN, POLLPRI, POLLOUT etc. These defines clash with cURL's
lib/select.h.

Make sure HAVE_STRUCT_POLLFD is defined then.

Bug: http://curl.haxx.se/bug/view.cgi?id=1282
Reported-by: "kdekker"
Patch-by: Marcel Raad
2013-09-28 23:18:19 +02:00
Steve Holme
a377fab015 ssluse.c: Fixed compilation warnings when ENGINE not supported
The function "ssl_ui_reader" was declared but never referenced
The function "ssl_ui_writer" was declared but never referenced
2013-09-28 17:24:22 +01:00
Daniel Stenberg
092f33d6bf configure: use icc options without space
The latest version(s) of the icc compiler no longer accept the extra
space in the -we (warning enable), -wd (warning disable), etc.

Reported-by: Elmira A Semenova
Bug: http://curl.haxx.se/mail/lib-2013-09/0182.html
2013-09-27 10:57:20 +02:00
Steve Holme
09a13a1c01 imap: Added clarification to the code about odd continuation responses 2013-09-25 17:44:51 +01:00
Steve Holme
30a09783b2 ftp.c: Fixed compilation warning
There is an implicit conversion from "unsigned long" to "long"
2013-09-25 07:09:41 +01:00
Steve Holme
733a4419d0 sasl: Centralised the authentication mechanism strings
Moved the standard SASL mechanism strings into curl_sasl.h rather than
hard coding the same values over and over again in the protocols that
use SASL authentication.

For more information about the mechanism strings see:

http://www.iana.org/assignments/sasl-mechanisms
2013-09-24 20:12:50 +01:00
Daniel Stenberg
77dc4ba877 RELEASE-NOTES: added recent contributors missing 2013-09-23 23:23:51 +02:00
Steve Holme
14d8209adc test906: Fixed type-2 response 2013-09-23 07:10:25 +01:00
Steve Holme
a942d8ff5b test915: Corrected test number from commit 22bccb0eda 2013-09-23 00:19:56 +01:00
Steve Holme
1695c67818 test906: Fixed type-1 message not handled error
...from commit f81d1e1666 due to copy paste error.
2013-09-23 00:15:37 +01:00
Steve Holme
f81d1e1666 tests: Added SMTP AUTH NTLM test 2013-09-22 20:53:29 +01:00
Steve Holme
b71ed1fb3d tests: Added SMTP multiple and invalid --mail-rcpt test 2013-09-22 20:25:32 +01:00
Steve Holme
86ccfaa3fd tests: Added SMTP multiple --mail-rcpt test 2013-09-22 20:23:27 +01:00
Steve Holme
3b69462fc0 tests: Added SMTP invalid --mail-rcpt test 2013-09-22 20:12:20 +01:00
Steve Holme
22bccb0eda tests: Regrouping of SMTP tests 2013-09-22 20:09:57 +01:00
Benoit Sigoure
4f591b9148 test1112: Increase the timeout from 7s to 16s
As someone reported on the mailing list a while back, the hard-coded
arbitrary timeout of 7s in test 1112 is not sufficient in some build
environments. At Arista Networks we build and test curl as part of our
automated build system, and we've run into this timeout 170 times so
far. Our build servers are typically quite busy building and testing a
lot of code in parallel, so despite being beefy machines with 32 cores
and 128GB of RAM we still hit this 7s timeout regularly.

URL: http://curl.haxx.se/mail/lib-2010-02/0200.html
2013-09-22 18:23:09 +02:00
Steve Holme
52cefc8cd7 tests: Fixed smtp rcpt to addresses 2013-09-22 15:14:26 +01:00
Steve Holme
8880f84e1a ftpserver.pl: Expanded the SMTP RCPT handler to validate TO addresses
RCPT_smtp() will now check for a correctly formatted TO address which
allows for invalid recipient addresses to be added.
2013-09-22 15:05:43 +01:00
Steve Holme
9d4a8c7936 ftpserver.pl: Added cURL SMTP server detection to HELO command handler
As curl will send a HELO command after an negative EHLO response, added
the same detection from commit b07709f741 to the HELO handler to
ensure the test server is identified correctly and an upload isn't
performed.
2013-09-22 13:21:15 +01:00
Steve Holme
fd8dc21fd0 ftpserver.pl: Corrected response code for successful RCPT command 2013-09-22 12:59:28 +01:00
Steve Holme
8ec6486d05 ftpserver.pl: Moved invalid RCPT TO: address detection to RCPT handler
Rather than detecting the TO address as missing in the DATA handler,
moved the detection to the RCPT command handler where an error response
can be generated.
2013-09-22 11:03:18 +01:00
Steve Holme
59c1743c78 RELEASE-NOTES: Corrected missed addition
Somehow commit 60a2046162 missed the last item in the sync list
even though I'm sure I added it during editing.
2013-09-21 22:28:07 +01:00
Steve Holme
60a2046162 RELEASE-NOTES: Synced with 6dd8bd8d2f 2013-09-21 22:20:40 +01:00
Steve Holme
6dd8bd8d2f curl.1: Added information about optional login options to --user in manpage
Added missing information, from curl 7.31.0, regarding the use of the
optional login options that may be specified as part of --user.

For example:

--user 'user:password;auth=NTLM' in IMAP, POP3 and SMTP protocols.
2013-09-21 22:05:12 +01:00
Steve Holme
b07709f741 ftpserver.pl: Moved cURL SMTP server detection into EHLO command handler
Moved the special SMTP server detection code from the DATA command
handler, which happens further down the operation chain after EHLO,
MAIL and RCPT commands, to the EHLO command as it is the first command
to be generated by a SMTP operation as well as containing the special
"verifiedserver" string from the URL.

This not only makes it easier and quicker to detect but also means that
cURL doesn't need to specify "verifiedserver" as --mail-from and
--mail-rcpt arguments.

More importantly, this also makes the upcoming verification changes to
the RCPT handler easier to implement.
2013-09-21 20:49:23 +01:00
Daniel Stenberg
9215cee4c6 openssl: use correct port number in error message
In ossl_connect_step2() when the "Unknown SSL protocol error" occurs, it
would output the local port number instead of the remote one which
showed when doing SSL over a proxy (but with the correct remote host
name). As libcurl only speaks SSL to the remote we know it is the remote
port.

Bug: http://curl.haxx.se/bug/view.cgi?id=1281
Reported-by: Gordon Marler
2013-09-21 21:01:00 +02:00
Daniel Stenberg
34df869f99 test1415: adjusted to work for 32bit time_t
The libcurl date parser returns INT_MAX for all dates > 2037 so this
test is now made to use 2037 instead of 2038 to work the same for both
32bit and 64bit time_t systems.
2013-09-21 13:46:42 -05:00
Steve Holme
3f04d48495 tests: Reworked existing SMTP tests to be single recipient based
...in preparation of upcoming multiple recipient tests.
2013-09-21 19:44:09 +01:00
Steve Holme
517b8e2290 ftpserver.pl: Corrected SMTP QUIT response to be more realistic 2013-09-20 23:08:28 +01:00
Daniel Stenberg
af44da38d6 curl_easy_setopt.3: clarify that TIMEOUT and TIMEOUT_MS set the same value 2013-09-20 23:16:04 +02:00
Kim Vandry
fcfa26a7ee Documented --dns-* options in curl manpage 2013-09-20 23:09:39 +02:00
Steve Holme
18db743851 pop3: Added basic SASL XOAUTH2 support
Added the ability to use an XOAUTH2 bearer token [RFC6750] with POP3 for
authentication using RFC6749 "OAuth 2.0 Authorization Framework".

The bearer token is expected to be valid for the user specified in
conn->user. If CURLOPT_XOAUTH2_BEARER is defined and the connection has
an advertised auth mechanism of "XOAUTH2", the user and access token are
formatted as a base64 encoded string and sent to the server as
"AUTH XOAUTH2 <bearer token>".
2013-09-20 21:56:30 +01:00
Steve Holme
0e188e2dc3 curl: Added clarification to the --mail options in the --help output
... that these options apply to SMTP only.
2013-09-20 21:35:44 +01:00
Steve Holme
eecb0e969f ftpserver.pl: Moved SMTP RCPT response text into command handler 2013-09-20 21:25:48 +01:00
Steve Holme
bd7d56ec71 tests: Added SMTP invalid --mail-from test 2013-09-20 07:09:39 +01:00
Nick Zitzmann
6f78aaad6f darwinssl: enable BEAST workaround on iOS 7 & later
iOS 7 finally added the option to enable 1/n-1 when using TLS 1.0
and a CBC cipher, so we now always turn that on unless the user
manually turns it off using CURLSSLOPT_ALLOW_BEAST.

It appears Apple also added some new PSK ciphers, but no interface to
use them yet, so we at least support printing them if we find them.
2013-09-19 17:28:54 -05:00
Steve Holme
89d320c2fd tests: Updated SMTP AUTH tests to use the new AUTH directive
...rather than specify a customised EHLO response.
2013-09-19 20:29:59 +01:00
Steve Holme
b809bafb0c tests: Corrected test913 as the QUIT response is received 2013-09-19 20:13:08 +01:00
Steve Holme
3b6a1681dc tests: Added SMTP large message SIZE test 2013-09-19 18:17:11 +01:00
Steve Holme
9300bb826d ftpserver.pl: Updated email regex from commit 98f7ca7e97
...to not be as strict as it was rejecting valid numeric email
addresses.
2013-09-19 12:44:27 +01:00
Steve Holme
dfe7ee1429 tests: Fixed smtp mail from addresses 2013-09-19 07:19:25 +01:00
Steve Holme
841103c776 ftpserver.pl: Standardised CAPA and AUTH responses 2013-09-18 19:38:26 +01:00
Steve Holme
8d2335ca23 ftpserver.pl: Corrected POP3 QUIT reply to be more realistic 2013-09-18 19:37:03 +01:00
Steve Holme
04064e89c1 runtests.pl: Fixed syntax error in commit c873375123
Possible unintended interpolation in string at line 796
2013-09-18 19:32:20 +01:00
Steve Holme
c873375123 runtests.pl: Fixed smtp mail from address
Following changes to ftpserver.pl fixed the mail from address to be a
correctly formatted address otherwise the server response will be 501
Invalid address.
2013-09-18 18:04:26 +01:00
Steve Holme
62d232c131 ftpserver.pl: Fixed syntax error in commit 98f7ca7e97
Can't modify constant item in scalar assignment line 779, near "0;"
2013-09-18 12:58:34 +01:00
Steve Holme
98f7ca7e97 ftpserver.pl: Expanded the SMTP MAIL handler to validate messages
MAIl_smtp() will now check for a correctly formatted FROM address as
well as the optional SIZE parameter comparing it against the server
capability when specified.
2013-09-18 07:23:32 +01:00
YAMADA Yasuharu
4cfbb201c4 cookies: add expiration
Implement: Expired Cookies These following situation, curl removes
cookie(s) from struct CookieInfo if the cookie expired.
 - Curl_cookie_add()
 - Curl_cookie_getlist()
 - cookie_output()
2013-09-17 23:25:56 +02:00
Steve Holme
dc016567ce ftpserver.pl: Corrected response code for successful MAIL command 2013-09-17 22:10:17 +01:00
Steve Holme
96b68c57ce ftpserver.pl: Moved SMTP MAIL handler into own function 2013-09-17 22:09:30 +01:00
Steve Holme
158dfe2c5c dns: fix compilation with MinGW from commit df69440d05
Avoid 'interface' literal that some MinGW versions define as a macro

Additionally, corrected some very, very minor coding style errors.
2013-09-17 20:59:43 +01:00
Steve Holme
8f5336a2fa tests: Fixed test 1406 following recent changes in ftpserver.pl
By default the mail server doesn't send the SIZE capability but instead
it has to be specified as a supported capability.
2013-09-16 00:24:46 +01:00
Steve Holme
f8a9dbd391 tests: Added test for SMTP SIZE capability 2013-09-16 00:24:30 +01:00
Steve Holme
016879d477 ftpserver.pl: Added the ability to include spaces in capabilities
For example:

CAPA "SIZE 1048576" 8BITMIME BINARYMIME

will populate the capabilities list with the following in:

SIZE 1048576
8BITMIME
BINARYMIME
2013-09-15 20:56:16 +01:00
Steve Holme
c03335ec68 ftpserver.pl: Corrected response code for successful SMTP QUIT command 2013-09-15 20:09:49 +01:00
Steve Holme
894585784c ftpserver.pl: Fixed syntax error in commit 33c1f2876b
Can't modify constant item in postincrement line 727, near "i++"
2013-09-15 20:07:43 +01:00
Steve Holme
33c1f2876b ftpserver.pl: Added CAPA & AUTH directive support to the SMTP EHLO handler 2013-09-15 16:53:20 +01:00
Steve Holme
00ee5c5cf1 ftpserver.pl: Fixed SMTP QUIT handler from dadc495540 2013-09-15 12:47:36 +01:00
Steve Holme
dadc495540 ftpserver.pl: Moved SMTP EHLO and QUIT handlers in own functions 2013-09-15 09:20:53 +01:00
Steve Holme
eae86ba62d ftpserver.pl: Added support for SMTP HELO command
...and updated test902 as explicit HELO response is no longer required.
2013-09-15 09:10:11 +01:00
Steve Holme
e9cca79dd1 ftpserver.pl: Added mailbox check to IMAP SELECT handler 2013-09-15 09:00:13 +01:00
Steve Holme
4ba3b6c05a ftpserver.pl: Corrected invalid user details check
...in both the IMAP LOGIN and POP3 PASS handlers introduced in commit
187ac69374 and 84ad1569e5 respectively.
2013-09-15 00:31:55 +01:00
Steve Holme
187ac69374 ftpserver.pl: Moved IMAP LOGIN handler into own function 2013-09-14 20:52:29 +01:00
Steve Holme
84ad1569e5 ftpserver.pl: Moved POP3 USER and PASS handlers into own functions 2013-09-14 20:46:45 +01:00
Steve Holme
45e0a661ce ftpserver.pl: Corrected invalid argument check in POP3 TOP handler
...which was accidentally introduced in commit 4d6ef6297a.
2013-09-14 16:18:47 +01:00
Steve Holme
4d6ef6297a ftpserver.pl: Added capability prerequisite for extended POP3 commands 2013-09-14 15:04:26 +01:00
Steve Holme
b68c52704b tests: Updated descriptions to be more meaningful 2013-09-14 15:04:25 +01:00
Steve Holme
4f4dc5832d ftpserver.pl: Added support for IMAP NOOP command 2013-09-14 10:44:54 +01:00
Steve Holme
fbcefc0ce0 imap: Fixed response check for NOOP command 2013-09-14 10:44:28 +01:00
Steve Holme
83f6f58834 tests: Updated descriptions to be more meaningful 2013-09-14 10:41:17 +01:00
Daniel Stenberg
0a691f8935 curl.1: detail how short/long options work
URL: http://curl.haxx.se/bug/view.cgi?id=1279
Suggested-by: Jerry Krinock
2013-09-13 23:14:41 +02:00
Steve Holme
c243d45aad curl: Fixed usage of DNS options when not using c-ares resolver
Commit 32352ed6ad introduced various DNS options, however, these
would cause curl to exit with CURLE_NOT_BUILT_IN when c-ares wasn't
being used as the backend resolver even if the options weren't set
by the user.

Additionally corrected some minor coding style errors from the same
commit.
2013-09-13 18:50:11 +01:00
Daniel Stenberg
8a6dba520b curl_easy_setopt.3: mention RTMP URL quirks
URL: http://curl.haxx.se/bug/view.cgi?id=1278
Reported-by: Gorilla Maguila
2013-09-13 14:06:20 +02:00
Ben Greear
32352ed6ad curl: Add support for various DNS binding options.
(Passed on to c-ares.)

Allows something like this:

curl --dns-interface sta8 --dns-ipv4-addr 8.8.1.111 --interface sta8 \
--localaddr 8.8.1.111 --dns-servers 8.8.8.1 www.google.com

Signed-off-by: Ben Greear <greearb@candelatech.com>
2013-09-12 21:11:47 +02:00
Kim Vandry
df69440d05 libcurl: New options to bind DNS to local interfaces or IP addresses 2013-09-12 21:11:47 +02:00
Daniel Stenberg
345955e87e libcurl.3: for multi interface connections are held in the multi handle
... and a few more cleanups/clarifications
2013-09-12 13:59:05 +02:00
Steve Holme
6f5b46855c ftpserver.pl: Fixed missing comma from 7fd84b14d2 2013-09-12 11:52:19 +01:00
Steve Holme
5f93c5d658 ftpserver.pl: Fixed variable error introduced in 7fd84b14d2
Global symbol "$mailbox" requires explicit package name
2013-09-12 07:10:41 +01:00
Steve Holme
7fd84b14d2 ftpserver.pl: Added support for UID command 2013-09-11 20:27:13 +01:00
Steve Holme
f2403140f9 ftpserver.pl: Added support for LSUB command 2013-09-11 20:25:48 +01:00
Steve Holme
f3c9749a40 imap: Fixed response check for LSUB and UID commands 2013-09-11 20:15:21 +01:00
Steve Holme
3f6991766f ftpserver.pl: Added support for IMAP COPY command 2013-09-11 19:57:29 +01:00
Steve Holme
cfe5f7dbf4 ftpserver.pl: Added support for IMAP CLOSE and EXPUNGE commands 2013-09-11 18:19:38 +01:00
Steve Holme
5840c918d5 ftpserver.pl: Added support for POP3 RSET command 2013-09-11 18:11:33 +01:00
Steve Holme
b0afb00000 ftpserver.pl: Added the ability to remember what messages are deleted
...as this will be required for IMAP CLOSE and EXPUNGE commands as well
as the POP3 RSET command.
2013-09-11 18:10:28 +01:00
Daniel Stenberg
0b5ae7c80e NI_MAXSERV: remove all use of it
Solaris with the SunStudio Compiler is reportedly missing this define,
but as we're using it without any good reason on all the places it was
used I've now instead switched to just use sensible buffer sizes that
fit a 32 bit decimal number. Which also happens to be smaller than the
common NI_MAXSERV value which is 32 on most machines.

Bug: http://curl.haxx.se/bug/view.cgi?id=1277
Reported-by: D.Flinkmann
2013-09-10 23:18:43 +02:00
Daniel Stenberg
0d55f4e1bc http2: use the support HTTP2 draft version in the upgrade header
... instead of HTTP/2.0 to work fine with the nghttpx proxy/server.
2013-09-10 23:06:20 +02:00
Steve Holme
86d340af27 ldap.c: Fix compilation warning
warning: comparison between signed and unsigned integer expressions
2013-09-10 20:27:52 +01:00
Jiri Hruska
5c14a7f068 imap/pop3/smtp: Speed up SSL connection initialization
Don't wait for the next callback call (usually 1 second) before
continuing with protocol specific connection initialization.
2013-09-10 19:47:54 +01:00
Steve Holme
2879ffacfa ldap.c: Corrected build error from commit 857f999353 2013-09-10 19:30:07 +01:00
Steve Holme
d89eb55906 RELEASE-NOTES: Corrected duplicate in bfefe2400a 2013-09-10 15:35:20 +01:00
Steve Holme
4a85e60cfe RELEASE-NOTES: Corrected typo from bfefe2400a 2013-09-10 14:06:50 +01:00
Steve Holme
bfefe2400a RELEASE-NOTES: synced with 25c6890375 2013-09-10 13:12:56 +01:00
Daniel Stenberg
25c6890375 README.http2: explain nghttp2 a little 2013-09-10 00:21:27 +02:00
Steve Holme
eb6314260d tests: Added test for POP3 TOP command 2013-09-09 17:13:28 +01:00
Steve Holme
313c38c9de ftpserver.pl: Added support for POP3 TOP command 2013-09-09 17:13:25 +01:00
Steve Holme
ae6096471a tests: Added test for POP3 UIDL command 2013-09-09 17:10:40 +01:00
Steve Holme
66ea5c415b ftpserver.pl: Added support for POP3 UIDL command 2013-09-09 17:10:38 +01:00
Daniel Stenberg
2481ac358c http2: adjust to new nghttp2_pack_settings_payload proto
This function was modified in nghttp2 git commit a1c3f89c72e51
2013-09-09 15:18:09 +02:00
Kamil Dudka
c639d725a3 url: handle abortion by read/write callbacks, too
Otherwise, the FTP protocol would unnecessarily hang 60 seconds if
aborted in the CURLOPT_HEADERFUNCTION callback.

Reported by: Tomas Mlcoch
Bug: https://bugzilla.redhat.com/1005686
2013-09-09 13:23:04 +02:00
Daniel Stenberg
857f999353 ldap: fix the build for systems with ldap_url_parse()
Make sure that the custom struct fields are only used by code that
doesn't use a struct defintion from the outside.

Attempts to fix the problem introduced in 3dc6fc42bf
2013-09-09 09:39:08 +02:00
Jiri Hruska
6d9cddc513 pingpong: Check SSL library buffers for already read data
Otherwise the connection can get stuck during various phases, waiting
for new data on the socket using select() etc., but it will never be
received as the data has already been read into SSL library.
2013-09-09 07:40:40 +01:00
Steve Holme
e20e48cbf2 imap: Fixed calculation of transfer when partial FETCH received
The transfer size would be calculated incorrectly if the email contained
within the FETCH response, had been partially received by the pingpong
layer. As such the following, example output, would be seen if the
amount remaining was smaller than the amount received:

* Excess found in a non pipelined read: excess = 1394, size = 262,
  maxdownload = 262, bytecount = 1374
* transfer closed with -1112 bytes remaining to read

Bug: http://curl.haxx.se/mail/lib-2013-08/0170.html
Reported-by: John Dunn
2013-09-09 07:40:38 +01:00
Steve Holme
ee5e2cf6cb ftpserver.pl: Fixed empty array checks
...from commits 28427b4083 and e8313697b6.
2013-09-08 23:59:49 +01:00
Steve Holme
e8313697b6 ftpserver: Reworked AUTH support to allow for specifying the mechanisms
Renamed SUPPORTAUTH to AUTH and added support for specifying a list of
supported SASL mechanisms to return to the client.

Additionally added the directive to the FILEFORMAT document.
2013-09-08 21:47:56 +01:00
Steve Holme
28427b4083 ftpserver: Reworked CAPA support to allow for specifying the capabilities
Renamed SUPPORTCAPA to CAPA and added support for specifying a list of
supported capabilities to return to the client.

Additionally added the directive to the FILEFORMAT document.
2013-09-08 21:45:36 +01:00
Steve Holme
131649a121 ftpserver.pl: Corrected POP3 LIST as message numbers should be contiguous
The message numbers given in the LIST response are an index into the
list, which are only valid for the current session, rather than being a
unique message identifier. An index would only be missing from the LIST
response if a DELE command had been issued within the same session and
had not been committed by the end of session QUIT command. Once
committed the POP3 server will regenerate the message numbers in the
next session to be contiguous again. As such our LIST response should
list message numbers contiguously until we support a DELE command in the
same session.

Should a POP3 user require the unique message ID for any or all
messages then they should use the extended UIDL command. This command
will be supported by the test ftpserver in an upcoming commit.
2013-09-08 20:19:20 +01:00
Clemens Gruber
632b3d81d6 curl_easy_pause: suggest one way to unpause 2013-09-08 19:26:28 +02:00
Steve Holme
241aeadc50 tests: Updated descriptions to be more meaningful 2013-09-08 16:59:57 +01:00
Steve Holme
669e4ca366 tests: Added test for POP3 NOOP command 2013-09-08 16:59:55 +01:00
Steve Holme
c9617d9f93 ftpserver.pl: Added support for POP3 NOOP command 2013-09-08 16:45:52 +01:00
Steve Holme
f8986a2b34 ftpserver.pl: Fixed 'Use of uninitialized value $args in string ne' 2013-09-08 16:39:41 +01:00
Steve Holme
1b96ce04b2 tests: Added test for POP3 STAT command 2013-09-08 08:52:53 +01:00
Steve Holme
f851df88fb ftpserver.pl: Added support for POP STAT command 2013-09-08 08:49:40 +01:00
Steve Holme
18c595fde2 ftpserver.pl: Moved POP3 QUIT handler into own function 2013-09-08 08:44:49 +01:00
Steve Holme
56abdd07e7 ftpserver.pl: Reordered the POP3 handlers to be alphabetical
In preparation for additional POP3 tests, re-ordered the command
function defintions to be sorted alphabetically.
2013-09-08 02:48:34 +01:00
Steve Holme
7e06c336d6 ftpserver.pl: Corrected misaligned indentation in POP3 handlers
Fixed incorrect indentation used in both the RETR_pop3 and LIST_pop3
functions which was 5 and 9 characters rather than 4 and 8.
2013-09-08 02:48:33 +01:00
Steve Holme
8a4069fb17 tests: Added test for POP3 DELE command 2013-09-07 19:49:12 +01:00
Steve Holme
243ad539fe ftpserver.pl: Added support for POP3 DELE command 2013-09-07 19:31:46 +01:00
Daniel Stenberg
3d60590422 http2: include curl_memory.h
Detected by test 1132
2013-09-07 19:48:01 +02:00
Nick Zitzmann
08fa4fed70 http: fix build warning under LLVM
When building the code using LLVM Clang without NGHTTP2, I was getting
this warning:
../lib/http.h:155:1: warning: empty struct is a GNU extension [-Wgnu]
Placing a dummy variable into the data structure silenced the warning.
2013-09-07 10:00:11 -05:00
Daniel Stenberg
4344fa926a http2: actually init nghttp2 and send HTTP2-Settings properly 2013-09-07 13:01:43 +02:00
Daniel Stenberg
61672bde44 README.http2: how to use it best with the multi API? 2013-09-07 11:28:12 +02:00
Daniel Stenberg
13dbb41c49 http2: first embryo toward Upgrade: 2013-09-07 11:28:12 +02:00
Daniel Stenberg
e5c2354fd5 http: rename use_http_1_1 to use_http_1_1plus
Since it now actually says if 1.1 or a later version should be used.
2013-09-07 11:28:12 +02:00
Daniel Stenberg
09634f46fb configure: improve CURL_CHECK_COMPILER_PROTOTYPE_MISMATCH
The compiler test used a variable before it was assigned when it tried
to see how it acts on a mismatching prototype, which could cause a false
positive.
2013-09-07 11:15:18 +02:00
Petr Písař
0119a93b33 Pass password to OpenSSL engine by user interface
Recent OpenSSL uses user interface abstraction to negotiate access to
private keys in the cryprographical engines. An OpenSSL application is
expected to implement the user interface. Otherwise a default one
provided by OpenSSL (interactive standard I/O) will be used and the
aplication will have no way how to pass a password to the engine.

Longer-desc: http://curl.haxx.se/mail/lib-2013-08/0265.html
2013-09-07 00:11:21 +02:00
Daniel Stenberg
9fa42beddc urlglob: improved error messages and column number on bad use
Introduce a convenience macro and keep of the column better so that it
can point out the offending column better.

Updated test 75 accordingly.
2013-09-06 23:27:47 +02:00
Daniel Stenberg
d6cda9e8ab urlglob: avoid error code translation
By using the correct values from the start we don't have to translate
them!
2013-09-06 14:20:48 +02:00
Daniel Stenberg
2a7f1425d9 urlglob: avoid NULL pointer dereference
Thanks to clang-analyzer
2013-09-06 14:12:44 +02:00
Gisle Vanem
900ccc26ae http2: use correct include for snprintf
Using the first little merge of nghttp2 into libcurl, I stumbeled on the
missing 'snprintf' in MSVCRT. Isn't this how we do it for other libcurl
files?  I.e. use 'curl_msnprintf' and not 'snprintf' directly:
2013-09-06 13:56:35 +02:00
Daniel Stenberg
01d7bbbebe --data: mention CRLF treatment when reading from file 2013-09-06 13:52:56 +02:00
Geoff Beier
3dc6fc42bf LDAP: fix bad free() when URL parsing failed
When an error occurs parsing an LDAP URL, The ludp->lud_attrs[i] entries
could be freed even though they sometimes point to data within an
allocated area.

This change introduces a lud_attrs_dup[] array for the duplicated string
pointers, and it removes the unused lud_exts array.

Bug: http://curl.haxx.se/mail/lib-2013-08/0209.html
2013-09-06 13:32:49 +02:00
Nick Zitzmann
d2fe616e7e darwinssl: add support for PKCS#12 files for client authentication
I also documented the fact that the OpenSSL engine also supports them.
2013-09-05 18:57:06 -05:00
Daniel Stenberg
316ca865e3 symbols: added HTTP2 symbols and sorted list
CURL_HTTP_VERSION_2_0 and CURL_VERSION_HTTP2 are new
2013-09-05 12:04:41 +02:00
Daniel Stenberg
812d49db90 configure: add HTTP2 as a curl-config --feature output
Fixes the test 1014 failure
2013-09-05 12:03:24 +02:00
Daniel Stenberg
02370fff3a curl: unbreak --http1.0 again
I broke it in 2eabb7d590
2013-09-05 09:56:05 +02:00
Daniel Stenberg
e9de8e78f0 SASL: fix compiler warnings
comparison between signed and unsigned integer expressions

suggest parentheses around '&&' within '||' (twice)
2013-09-04 22:33:29 +02:00
Daniel Stenberg
2eabb7d590 curl: add --http1.1 and --http2.0 options 2013-09-04 22:29:38 +02:00
Daniel Stenberg
d707a975f6 Curl_setopt: refuse CURL_HTTP_VERSION_2_0 if built without support 2013-09-04 22:29:38 +02:00
Daniel Stenberg
ac487842a1 http2: add http2.[ch] and add nghttp2 version output 2013-09-04 22:29:38 +02:00
Daniel Stenberg
06b6e1d0d2 curl -V: output HTTP2 as a feature if present 2013-09-04 22:29:38 +02:00
Daniel Stenberg
b77997e6da curl.h: add CURL_VERSION_HTTP2 as a feature
It isn't added as a separate protocol as HTTP2 will be done over HTTP://
URLs that can be upgraded to HTTP2 if the server supports it as well.
2013-09-04 22:29:38 +02:00
Steve Holme
9e8ced9890 imap/smtp: Fixed incorrect SASL mechanism selection with XOAUTH2 servers
XOAUTH2 would be selected in preference to LOGIN and PLAIN if the IMAP
or SMTP server advertised support for it even though a user's password
was supplied but bearer token wasn't.

Modified the selection logic so that XOAUTH2 will only be selected if
the server supports it and A) The curl user/libcurl programmer has
specifically asked for XOAUTH via the ;AUTH=XOAUTH login option or 2)
The bearer token is specified. Obviously if XOAUTH is asked for via
the login option but no token is specified the user will receive a
authentication failure which makes more sense than no known
authentication mechanisms supported!
2013-09-04 21:27:01 +01:00
Daniel Stenberg
698e3bdf82 curl.h: added CURL_HTTP_VERSION_2_0
Initial library considerations documented in lib/README.http2
2013-09-04 10:05:00 +02:00
Daniel Stenberg
9011fb3f0c configure: added --with-nghttp2 2013-09-04 10:04:48 +02:00
Daniel Stenberg
073b03fab7 acinclude: fix --without-ca-path when cross-compiling
The commit 7b074a460b to CURL_CHECK_CA_BUNDLE in 7.31 (don't check
for paths when cross-compiling) causes --without-ca-path to no longer
works when cross-compiling, since ca and capath only ever get set to
"no" when not cross-compiling, I attach a patch that works for me. Also
in the cross-compilation case, no ca-path seems to be a better default
(IMVHO) than empty ca-path.

Bug: http://curl.haxx.se/bug/view.cgi?id=1273
Patch-by: Stefan Neis
2013-09-04 00:01:03 +02:00
Steve Holme
f73f052010 lib1512.c: Fixed compilation warning
An enumerated type is mixed with another type.

...as well as a small coding style error.
2013-09-02 20:39:53 +01:00
Guenter Knauf
97ed1ac905 Killed warning 'res' might be used uninitialized. 2013-09-01 23:08:29 +02:00
Steve Holme
322f0bc2f1 url.c: Fixed compilation warning
An enumerated type is mixed with another type
2013-09-01 13:30:12 +01:00
Steve Holme
af4bddf20b easy.c: Fixed compilation warning
warning: `code' might be used uninitialized in this function
2013-09-01 12:48:50 +01:00
Daniel Stenberg
f19efd07e7 -x: rephrased the --proxy section somewhat 2013-08-31 22:55:53 +02:00
Steve Holme
83f5332536 tests: Added test for IMAP CHECK command 2013-08-31 18:40:48 +01:00
Steve Holme
497775024c ftpserver.pl: Added support for the IMAP CHECK command 2013-08-31 18:40:46 +01:00
Guenter Knauf
ea38a70539 Removed reference to krb4.c. 2013-08-31 19:12:35 +02:00
Steve Holme
5eea336d01 ftpserver.pl: Corrected flawed logic in commit 1ca6ed7b75 2013-08-31 11:10:20 +01:00
Steve Holme
f3849a7b84 imap: Fixed response check for EXPUNGE command 2013-08-31 10:49:49 +01:00
Steve Holme
1ca6ed7b75 ftpserver.pl: Added argument check to IMAP command handlers
Added BAD argument check to the following IMAP command handlers:

APPEND, STORE, LIST, EXAMINE, STATUS and SEARCH
2013-08-31 10:41:25 +01:00
Steve Holme
aa51d3a139 ftpserver.pl: More whitespace corrections
LIST_imap() had a second level of indentation at 9 characters and not 8.
2013-08-31 10:35:05 +01:00
Steve Holme
64c8909071 ftpserver.pl: Small correction tidy up
Corrected some IMAP variable names and whitespace issues.
2013-08-30 22:11:17 +01:00
Kyle L. Huff
e848942505 docs: Added documentation for CURLOPT_BEARER 2013-08-30 21:43:13 +01:00
Kyle L. Huff
7e489c42f7 curl.1: Add usage of '--bearer' option 2013-08-30 21:34:20 +01:00
Steve Holme
75b52f9dcc tests: Added tests for IMAP CREATE, DELETE and RENAME commands 2013-08-30 18:56:56 +01:00
Daniel Stenberg
221825aebf ftpserver: Bareword "to_mailbox" not allowed
Added missing $
2013-08-30 15:21:39 +02:00
Steve Holme
9d35ad9552 ftpserver.pl: Added support for IMAP CREATE, DELETE and RENAME commands 2013-08-30 07:35:00 +01:00
Daniel Stenberg
c4a7ca038e FTP: fix getsock during DO_MORE state
... when doing upload it would return the wrong values at times. This
commit attempts to cleanup the mess.

Bug: http://curl.haxx.se/mail/lib-2013-08/0109.html
Reported-by: Mike Mio
2013-08-29 23:09:31 +02:00
Daniel Stenberg
84f3b3dd44 curl_multi_remove_handle: allow multiple removes
When removing an already removed handle, avoid that to ruin the
internals and just return OK instead.
2013-08-29 22:08:45 +02:00
Steve Holme
2ef83136d4 ftpserver.pl: Updated IMAP EXAMINE handler to use dynamic test data 2013-08-29 20:08:27 +01:00
Daniel Stenberg
d737aa19c8 unit1304: include memdebug and free everything correctly 2013-08-29 12:50:15 +02:00
Daniel Stenberg
78e6683bb0 Curl_parsenetrc: document that the arguments must be allocated 2013-08-29 12:49:56 +02:00
Daniel Stenberg
2f9b64ac33 easy: rename struct monitor to socketmonitor
'struct monitor', introduced in 6cf8413e, already exists in an IRIX
header file (sys/mon.h) which gets included via various standard headers
by lib/easy.c

cc-1101 cc: ERROR File = ../../curl/lib/easy.c, Line = 458
"monitor" has already been declared in the current scope.

Reported-by: Tor Arntsen
2013-08-29 09:58:11 +02:00
Steve Holme
6a353049ac ftpserver.pl: Added SELECT check to IMAP FETCH and STORE handlers 2013-08-29 07:20:03 +01:00
Steve Holme
49e3d803ab ftpserver.pl: Corrected accidental move of logmsg() call
Corrected the call to logmsg() in the IMAP SEARCH handler from commit
4ae7b7ea69 as it should have been outputting the what argument and
not the test number.
2013-08-28 22:58:33 +01:00
Daniel Stenberg
b644ae68c8 ftpserver: add missing '}' from 4ae7b7ea69 2013-08-28 22:59:19 +02:00
Steve Holme
4ae7b7ea69 ftpserver.pl: Added SELECT check to IMAP SEARCH command 2013-08-28 18:56:19 +01:00
Steve Holme
13a2e32548 ftpserver.pl: Fixed IMAP SEARCH command 2013-08-28 18:51:59 +01:00
Daniel Stenberg
c3b513e75c bump: next release is 7.33.0 due to added features 2013-08-28 09:32:48 +02:00
Daniel Stenberg
a74b36af2a symbols-in-versions: add CURLOPT_XOAUTH2_BEARER 2013-08-28 09:31:37 +02:00
Steve Holme
1b4dc10393 tests: Added test for IMAP SEARCH command 2013-08-28 07:27:10 +01:00
Daniel Stenberg
45b6e2dd89 valgrind.supp: fix for regular curl_easy_perform too
When we introduced curl_easy_perform_ev, this got a slightly modified
call trace. Without this, test 165 causes a false positive valgrind
error.
2013-08-28 00:09:27 +02:00
Daniel Stenberg
6dca35c0e5 valgrind.supp: add the event-based call stack-trace too
Without this, test 165 triggers a valgrind error when ran with
curl_easy_perform_ev
2013-08-28 00:07:12 +02:00
Daniel Stenberg
a691e04470 multi_socket: improved 100-continue timeout handling
When waiting for a 100-continue response from the server, the
Curl_readwrite() will refuse to run if called until the timeout has been
reached.

We timeout code in multi_socket() allows code to run slightly before the
actual timeout time, so for test 154 it could lead to the function being
executed but refused in Curl_readwrite() and then the application would
just sit idling forever.

This was detected with runtests.pl -e on test 154.
2013-08-28 00:07:12 +02:00
Steve Holme
3d1a453d88 ftpserver.pl: Added support for IMAP SEARCH command 2013-08-27 20:47:31 +01:00
Steve Holme
d7a39f8f97 tool_operate.c: Fixed compilation warning
warning: implicit declaration of function 'checkpasswd'
2013-08-27 16:39:16 +01:00
Steve Holme
3c929ff9f6 curl: Moved check for password out of get parameter loop
Moved the calls to checkpasswd() out of the getparameter() function
which allows for any related arguments to be specified on the command
line before or after --user (and --proxy-user).

For example: --bearer doesn't need to be specified before --user to
prevent curl from asking for an unnecessary password as is the case
with commit e7dcc454c6.
2013-08-27 15:31:21 +01:00
Steve Holme
9d957294cb RELEASE-NOTES: synced with acf59be7f0 2013-08-26 23:27:07 +01:00
Kyle L. Huff
acf59be7f0 curl: added --bearer option to help
Added the --bearer option to the help output
2013-08-26 20:44:05 +01:00
Kyle L. Huff
e7dcc454c6 curl: added basic SASL XOAUTH2 support
Added the ability to specify an XOAUTH2 bearer token [RFC6750] via the
--bearer option.

Example usage:
  curl --url "imaps://imap.gmail.com:993/INBOX/;UID=1" --ssl-reqd
  --bearer ya29.AHES6Z...OMfsHYI --user username@example.com
2013-08-26 20:43:02 +01:00
Steve Holme
84789e12fb tool_urlglob.c: Fixed compiler warnings
warning: 'variable' may be used uninitialized in this function
2013-08-26 11:41:35 +01:00
Daniel Stenberg
460fb12097 security.h: rename to curl_sec.h to avoid name collision
I brought back security.h in commit bb55293313. As we actually
already found out back in 2005 in commit 62970da675, the file name
security.h causes problems so I renamed it curl_sec.h instead.
2013-08-26 11:51:18 +02:00
Daniel Stenberg
63d8b3a507 runtests.pl: allow -vc point to a separate curl binary to verify with
The specified curl binary will then be used to verify the running
server(s) instead of the development version. This is very useful in
some cases when the development version fails to verify correctly as
then the test case may not run at all.

The actual test will still be run with the "normal" curl executable
(unless the test case specifies something differently).
2013-08-26 11:38:38 +02:00
Kyle L. Huff
90ab65c632 smtp: added basic SASL XOAUTH2 support
Added the ability to use an XOAUTH2 bearer token [RFC6750] with SMTP for
authentication using RFC6749 "OAuth 2.0 Authorization Framework".

The bearer token is expected to be valid for the user specified in
conn->user. If CURLOPT_XOAUTH2_BEARER is defined and the connection has
an advertised auth mechanism of "XOAUTH2", the user and access token are
formatted as a base64 encoded string and sent to the server as
"AUTH XOAUTH2 <bearer token>".
2013-08-26 10:16:44 +01:00
Kyle L. Huff
34122800b8 imap: added basic SASL XOAUTH2 support
Added the ability to use an XOAUTH2 bearer token [RFC6750] with IMAP for
authentication using RFC6749 "OAuth 2.0 Authorization Framework".

The bearer token is expected to be valid for the user specified in
conn->user. If CURLOPT_XOAUTH2_BEARER is defined and the connection has
an advertised auth mechanism of "XOAUTH2", the user and access token are
formatted as a base64 encoded string and sent to the server as
"A001 AUTHENTICATE XOAUTH2 <bearer token>".
2013-08-26 10:16:32 +01:00
Steve Holme
7f41eab395 security.h: Fixed compilation warning
ISO C forbids forward references to 'enum' types
2013-08-26 10:14:16 +01:00
Daniel Stenberg
0192ad65bb KNOWN_BUGS: refer to bug numbers with the existing number series
The old numbers would still redirect but who knows for how long...
2013-08-26 00:29:33 +02:00
Kyle L. Huff
06c1bea72f options: added basic SASL XOAUTH2 support
Added the ability to specify an XOAUTH2 bearer token [RFC6750] via the
option CURLOPT_XOAUTH2_BEARER for authentication using RFC6749 "OAuth
2.0 Authorization Framework".
2013-08-25 22:03:57 +01:00
Kyle L. Huff
19a05c908f sasl: added basic SASL XOAUTH2 support
Added the ability to generated a base64 encoded XOAUTH2 token
containing: "user=<username>^Aauth=Bearer <bearer token>^A^A"
as per RFC6749 "OAuth 2.0 Authorization Framework".
2013-08-25 22:02:38 +01:00
Daniel Stenberg
bb55293313 FTP: remove krb4 support
We've announced this pending removal for a long time and we've
repeatedly asked if anyone would care or if anyone objects. Nobody has
objected. It has probably not even been working for a good while since
nobody has tested/used this code recently.

The stuff in krb4.h that was generic enough to be used by other sources
is now present in security.h
2013-08-25 19:16:36 +02:00
Daniel Stenberg
817ceb09e0 easy: define away easy_events() for non-debug builds 2013-08-25 19:10:02 +02:00
Daniel Stenberg
1a911f7ec4 FAQ: editorial updates
Several language fixes. Several reformats that should make the HTML
generation of this document look better.

Reported-by: Dave Thompson
2013-08-24 17:13:46 +02:00
Daniel Stenberg
ea464d72e9 RELEASE-NOTES: synced with 22adb46a32 2013-08-23 15:39:03 +02:00
Daniel Stenberg
22adb46a32 multi: move on from STATE_DONE faster
Make sure we always return CURLM_CALL_MULTI_PERFORM when we reach
CURLM_STATE_DONE since the state is transient and it can very well
continue executing as there is nothing to wait for.

Bug: http://curl.haxx.se/mail/lib-2013-08/0211.html
Reported-by: Yi Huang
2013-08-22 22:55:25 +02:00
Daniel Stenberg
fc99eaa5ae curl.h: name space pollution by "enum type"
Renamed to "enum curl_khtype" now. Will break compilation for programs
that rely on the enum name.

Bug: https://github.com/bagder/curl/pull/76
Reported-by: Shawn Landden
2013-08-22 22:45:51 +02:00
Daniel Stenberg
4bea91fc67 TFTP: make the CURLOPT_LOW_SPEED* options work
... this also makes sure that the progess callback gets called more
often during TFTP transfers.

Added test 1238 to verify.

Bug: http://curl.haxx.se/bug/view.cgi?id=1269
Reported-by: Jo3
2013-08-22 22:42:27 +02:00
Daniel Stenberg
06d1b10cbe tftpd: support "writedelay" within <servercmd> 2013-08-22 19:23:08 +02:00
Daniel Stenberg
816b639035 tftpd: convert 6 global variables into local ones 2013-08-22 13:44:37 +02:00
Gisle Vanem
8804ffd4fa curl_easy_perform_ev: make it CURL_EXTERN
I build curl.exe (using MingW) with '-DCURLDEBUG' and by importing from
libcurl.dll.  Which means the new curl_easy_perform_ev() must be
exported from libcurl.dll.
2013-08-21 22:19:52 +02:00
Daniel Stenberg
19122c0768 CURLM_ADDED_ALREADY: new error code
Doing curl_multi_add_handle() on an easy handle that is already added to
a multi handle now returns this error code. It previously returned
CURLM_BAD_EASY_HANDLE for this condition.
2013-08-20 23:13:19 +02:00
Daniel Stenberg
c346c4c8f9 multi_init: moved init code here from add_handle
The closure_handle is "owned" by the multi handle and it is
unconditional so the setting up of it should be in the Curl_multi_handle
function rather than curl_multi_add_handle.
2013-08-20 23:13:19 +02:00
Daniel Stenberg
bc7d806e3a multi: remove dns cache creation code from *add_handle
As it is done unconditionally in multi_init() this code will never run!
2013-08-20 23:13:19 +02:00
Daniel Stenberg
6cf8413e31 curl_easy_perform_ev: debug/test function
This function is meant to work *exactly* as curl_easy_perform() but will
use the event-based libcurl API internally instead of
curl_multi_perform(). To avoid relying on an actual event-based library
and to not use non-portable functions (like epoll or similar), there's a
rather inefficient emulation layer implemented on top of Curl_poll()
instead.

There's currently some convenience logging done in curl_easy_perform_ev
which helps when tracking down problems. They may be suitable to remove
or change once things seem to be fine enough.

curl has a new --test-event option when built with debug enabled that
then uses curl_easy_perform_ev() instead of curl_easy_perform(). If
built without debug, using --test-event will only output a warning
message.

NOTE: curl_easy_perform_ev() is not part if the public API on purpose.
It is only present in debug builds of libcurl and MUST NOT be considered
stable even then. Use it for libcurl-testing purposes only.

runtests.pl now features an -e command line option that makes it use
--test-event for all curl command line tests. The man page is updated.
2013-08-20 11:56:06 +02:00
Gisle Vanem
062e5bfd9c transfer: the recent sessionhandle change broke CURL_DOES_CONVERSIONS 2013-08-20 11:42:34 +02:00
Daniel Stenberg
e4a1888bd0 test1237: verify 1000+ letter user name + passwords 2013-08-20 11:23:31 +02:00
Jonathan Nieder
2f1a0bc0bf url: handle arbitrary-length username and password before '@'
libcurl quietly truncates usernames, passwords, and options from
before an '@' sign in a URL to 255 (= MAX_CURL_PASSWORD_LENGTH - 1)
characters to fit in fixed-size buffers on the stack.  Allocate a
buffer large enough to fit the parsed fields on the fly instead to
support longer passwords.

After this change, there are no more uses of MAX_CURL_OPTIONS_LENGTH
left, so stop defining that constant while at it.  The hardcoded max
username and password length constants, on the other hand, are still
used in HTTP proxy credential handling (which this patch doesn't
touch).

Reported-by: Colby Ranger
2013-08-20 11:16:38 +02:00
Jonathan Nieder
09ddb1d61c url: handle exceptional cases first in parse_url_login()
Instead of nesting "if(success)" blocks and leaving the reader in
suspense about what happens in the !success case, deal with failure
cases early, usually with a simple goto to clean up and return from
the function.

No functional change intended.  The main effect is to decrease the
indentation of this function slightly.
2013-08-20 11:16:38 +02:00
Jonathan Nieder
15f76bf7bb Curl_setopt: handle arbitrary-length username and password
libcurl truncates usernames, passwords, and options set with
curl_easy_setopt to 255 (= MAX_CURL_PASSWORD_LENGTH - 1) characters.
This doesn't affect the return value from curl_easy_setopt(), so from
the caller's point of view, there is no sign anything strange has
happened, except that authentication fails.

For example:

  # Prepare a long (300-char) password.
  s=0123456789; s=$s$s$s$s$s$s$s$s$s$s; s=$s$s$s;
  # Start a server.
  nc -l -p 8888 | tee out & pid=$!
  # Tell curl to pass the password to the server.
  curl --user me:$s http://localhost:8888 & sleep 1; kill $pid
  # Extract the password.
  userpass=$(
	awk '/Authorization: Basic/ {print $3}' <out |
	tr -d '\r' |
	base64 -d
  )
  password=${userpass#me:}
  echo ${#password}

Expected result: 300
Actual result: 255

The fix is simple: allocate appropriately sized buffers on the heap
instead of trying to squeeze the provided values into fixed-size
on-stack buffers.

Bug: http://bugs.debian.org/719856
Reported-by: Colby Ranger
2013-08-20 11:16:38 +02:00
Jonathan Nieder
36585b5395 netrc: handle longer username and password
libcurl truncates usernames and passwords it reads from .netrc to
LOGINSIZE and PASSWORDSIZE (64) characters without any indication to
the user, to ensure the values returned from Curl_parsenetrc fit in a
caller-provided buffer.

Fix the interface by passing back dynamically allocated buffers
allocated to fit the user's input.  The parser still relies on a
256-character buffer to read each line, though.

So now you can include an ~246-character password in your .netrc,
instead of the previous limit of 63 characters.

Reported-by: Colby Ranger
2013-08-20 11:16:38 +02:00
Jonathan Nieder
11baffbff6 url: allocate username, password, and options on the heap
This makes it possible to increase the size of the buffers when needed
in later patches.  No functional change yet.
2013-08-20 11:16:38 +02:00
Jonathan Nieder
53333a43a1 url: use goto in create_conn() for exception handling
Instead of remembering before each "return" statement which temporary
allocations, if any, need to be freed, take care to set pointers to
NULL when no longer needed and use a goto to a common block to exit
the function and free all temporaries.

No functional change intended.  Currently the only temporary buffer in
this function is "proxy" which is already correctly freed when
appropriate, but there will be more soon.
2013-08-20 11:16:38 +02:00
Jonathan Nieder
c56f9797e7 sasl: allow arbitrarily long username and password
Use appropriately sized buffers on the heap instead of fixed-size
buffers on the stack, to allow for longer usernames and passwords.

Callers never pass anything longer than MAX_CURL_USER_LENGTH (resp.
MAX_CURL_PASSWORD_LENGTH), so no functional change inteded yet.
2013-08-20 11:16:38 +02:00
Alex McLellan
9281be36d5 imap: Fixed response check for SEARCH command
Adding this line allows libcurl to return the server response when
performing a search command via a custom request.
2013-08-19 10:23:14 +01:00
Daniel Stenberg
f15a88f2b2 glob: error out on range overflow
The new multiply() function detects range value overflows. 32bit
machines will overflow on a 32bit boundary while 64bit hosts support
ranges up to the full 64 bit range.

Added test 1236 to verify.

Bug: http://curl.haxx.se/bug/view.cgi?id=1267
Reported-by: Will Dietz
2013-08-16 11:55:04 +02:00
Daniel Stenberg
5ca96cb844 urlglob: better detect unclosed braces, empty lists and overflows
A rather big overhaul and cleanup.

1 - curl wouldn't properly detect and reject globbing that ended with an
open brace if there were brackets or braces before it. Like "{}{" or
"[0-1]{"

2 - curl wouldn't properly reject empty lists so that "{}{}" would
result in curl getting (nil) strings in the output.

3 - By using strtoul() instead of sscanf() the code will now detected
over and underflows. It now also better parses the step argument to only
accept positive numbers and only step counters that is smaller than the
delta between the maximum and minimum numbers.

4 - By switching to unsigned longs instead of signed ints for the
counters, the max values for []-ranges are now very large (on 64bit
machines).

5 - Bumped the maximum number of globs in a single URL to 100 (from 10)

6 - Simplified the code somewhat and now it stores fixed strings as
single- entry lists. That's also one of the reasons why I did (5) as now
all strings between "globs" will take a slot in the array.

Added test 1234 and 1235 to verify. Updated test 87.

This commit fixes three separate bug reports.

Bug: http://curl.haxx.se/bug/view.cgi?id=1264
Bug: http://curl.haxx.se/bug/view.cgi?id=1265
Bug: http://curl.haxx.se/bug/view.cgi?id=1266
Reported-by: Will Dietz
2013-08-16 11:52:08 +02:00
John Malmberg
10afe7cf10 VMS: Add RELEASE-NOTES to vms document
Add the curl release notes to the release note document generated for
VMS packages.

Add the different filenames generated by a daily build to the
cleanup procedures.
2013-08-15 10:57:52 +02:00
Tor Arntsen
6972335f50 tests 2032, 2033: Don't hardcode port in expected output 2013-08-15 10:55:44 +02:00
Daniel Stenberg
d5e2d0b6bf ftp: convert state names to a global array
... just to make them easier to print in debug ouputs while debugging.
They are still within #ifdef [debugbuild].
2013-08-14 22:41:30 +02:00
Daniel Stenberg
f34b5fb4d8 --help: fix the --sasl-ir in the help output 2013-08-14 22:39:58 +02:00
Daniel Stenberg
f584312e81 ftp_domore_getsock: when passive mode, the second conn is already there
This makes the socket callback get called with the proper bitmask as
otherwise the application could be left hanging waiting for reading on
an upload connection!

Bug: http://curl.haxx.se/mail/lib-2013-08/0043.html
Reported-by: Bill Doyle
2013-08-14 22:30:24 +02:00
Daniel Stenberg
0b4557f766 curl: make --no-[option] work properly for several options
--create-dirs, --crlf, --socks5-gssapi-nec and --sasl-ir
2013-08-14 11:39:04 +02:00
Kamil Dudka
204126a5f1 nss: make sure that NSS is initialized
... prior to calling PK11_GenerateRandom()
2013-08-12 15:17:39 +02:00
Daniel Stenberg
2ae3d28f3d multi: s/easy/data
With everything being struct SessionHandle pointers now, this rename
makes multi.c use the library-wide practise of calling that pointer
'data' instead of the previously used 'easy'.
2013-08-12 13:52:58 +02:00
Daniel Stenberg
8a42c2ef8d cleanup: removed one function, made one static
Moved Curl_easy_addmulti() from easy.c to multi.c, renamed it to
easy_addmulti and made it static.

Removed Curl_easy_initHandleData() and uses of it since it was emptied
in commit cdda92ab67b47d74a.
2013-08-12 13:17:57 +02:00
Daniel Stenberg
e79535bc5e SessionHandle: the protocol specific pointer is now a void *
All protocol handler structs are now opaque (void *) in the
SessionHandle struct and moved in the request-specific sub-struct
'SingleRequest'. The intension is to keep the protocol specific
knowledge in their own dedicated source files [protocol].c etc.

There's some "leakage" where this policy is violated, to be addressed at
a later point in time.
2013-08-12 13:17:57 +02:00
Daniel Stenberg
4ad8e142da urldata: clean up the use of the protocol specific structs
1 - always allocate the struct in protocol->setup_connection. Some
protocol handlers had to get this function added.

2 - always free at the end of a request. This is also an attempt to keep
less memory in the handle after it is completed.
2013-08-12 13:17:57 +02:00
Daniel Stenberg
e3ee73b70c version number: bump to 7.32.1 for now
Start working on the next version and up some counters.
2013-08-12 13:16:44 +02:00
148 changed files with 6286 additions and 2944 deletions

View File

@@ -1,69 +1,68 @@
Curl and libcurl 7.32.0
Curl and libcurl 7.33.0
Public curl releases: 134
Command line options: 152
curl_easy_setopt() options: 199
Public curl releases: 135
Command line options: 161
curl_easy_setopt() options: 205
Public functions in libcurl: 58
Known libcurl bindings: 42
Contributors: 1049
***
krb4 support is up for removal. If you care about it at all, speak up
on the curl-library list asap!
***
Contributors: 1057
This release includes the following changes:
o curl: allow timeouts to accept decimal values
o OS400: add slist and certinfo EBCDIC support
o OS400: new SSL backend GSKit
o CURLOPT_XFERINFOFUNCTION: introducing a new progress callback
o LIBCURL-STRUCTS: new document
o test code for testing the event based API [3]
o CURLM_ADDED_ALREADY: new error code
o test TFTP server: support "writedelay" within <servercmd>
o krb4 support has been removed
o imap/pop3/smtp: added basic SASL XOAUTH2 support [9]
o darwinssl: add support for PKCS#12 files for client authentication
o darwinssl: enable BEAST workaround on iOS 7 & later
o Pass password to OpenSSL engine by user interface [15]
o c-ares: Add support for various DNS binding options
o cookies: add expiration
o curl: added --oauth2-bearer option
This release includes the following bugfixes:
o dotdot: introducing dot file path cleanup [1]
o docs: fix typo in curl_easy_getinfo manpage
o test1230: avoid using hard-wired port number
o test1396: invoke the correct test tool
o SIGPIPE: ignored while inside the library [2]
o darwinssl: fix crash that started happening in Lion
o OpenSSL: check for read errors, don't assume [3]
o c-ares: improve error message on failed resolve [4]
o printf: make sure %x are treated unsigned
o formpost: better random boundaries [5]
o url: restore the functionality of 'curl -u :' [6]
o curl.1: fix typo in --xattr description [7]
o digest: improve nonce generation
o configure: automake 1.14 compatibility tweak
o curl.1: document the --post303 option in the man page
o curl.1: document the --sasl-ir option in the man page
o setup-vms.h: sk_pop symbol tweak
o tool_paramhlp: try harder to catch negatives
o cmake: Fix for MSVC2010 project generation [8]
o asyn-ares: Don't blank ares servers if none configured
o curl_multi_wait: set revents for extra fds
o Reinstate "WIN32 MemoryTracking: track wcsdup() _wcsdup() and _tcsdup()
o ftp_do_more: consider DO_MORE complete when server connects back [9]
o curl_easy_perform: gradually increase the delay time [10]
o curl: fix symbolic names for CURLUSESSL_* enum in --libcurl output
o curl: fix upload of a zip file in OpenVMS [11]
o build: fix linking on Solaris 10 [12]
o curl_formadd: CURLFORM_FILECONTENT wrongly rejected some option combos [13]
o curl_formadd: fix file upload on VMS [14]
o curl_easy_pause: on unpause, trigger mulit-socket handling [15]
o md5 & metalink: use better build macros on Apple operating systems [16]
o darwinssl: fix build error in crypto authentication under Snow Leopard [16]
o curl: make --progress-bar update the line less frequently [17]
o configure: don't error out on variable confusions (CFLAGS, LDFLAGS etc)
o mk-ca-bundle: skip more untrusted certificates
o formadd: wrong pointer for file name when CURLFORM_BUFFERPTR used [18]
o FTP: when EPSV gets a 229 but fails to connect, retry with PASV
o mk-ca-bundle.1: don't install on make install [19]
o VMS: lots of updates and fixes of the build procedure
o global dns cache: didn't work (regression)
o global dns cache: fix memory leak
o
o nss: make sure that NSS is initialized
o curl: make --no-[option] work properly for several options
o FTP: with socket_action send better socket updates in active mode [1]
o curl: fix the --sasl-ir in the --help output
o tests 2032, 2033: Don't hardcode port in expected output
o urlglob: better detect unclosed braces, empty lists and overflows [7]
o urlglob: error out on range overflow [8]
o imap: Fixed response check for SEARCH, EXPUNGE, LSUB, UID and NOOP commands [10]
o handle arbitrary-length username and password [2]
o TFTP: make the CURLOPT_LOW_SPEED* options work [4]
o curl.h: name space pollution by "enum type" [5]
o multi: move on from STATE_DONE faster [6]
o FTP: 60 secs delay if aborted in the CURLOPT_HEADERFUNCTION callback [11]
o multi_socket: improved 100-continue timeout handling
o curl_multi_remove_handle: allow multiple removes
o FTP: fix getsock during DO_MORE state [12]
o -x: rephrased the --proxy section somewhat
o acinclude: fix --without-ca-path when cross-compiling [13]
o LDAP: fix bad free() when URL parsing failed [14]
o --data: mention CRLF treatment when reading from file
o curl_easy_pause: suggest one way to unpause
o imap: Fixed calculation of transfer when partial FETCH received [16]
o pingpong: Check SSL library buffers for already read data [16]
o imap/pop3/smtp: Speed up SSL connection initialization
o libcurl.3: for multi interface connections are held in the multi handle
o curl_easy_setopt.3: mention RTMP URL quirks [17]
o curl.1: detail how short/long options work [18]
o curl.1: Added information about optional login options to --user option
o curl: Added clarification to the --mail options in the --help output
o curl_easy_setopt.3: clarify that TIMEOUT and TIMEOUT_MS set the same value
o openssl: use correct port number in error message [19]
o darwinssl: block TLS_RSA_WITH_NULL_SHA256 cipher
o OpenSSL: acknowledge CURLOPT_SSL_VERIFYHOST without VERIFYPEER
o xattr: add support for FreeBSD xattr API
o win32: fix Visual Studio 2010 build with WINVER >= 0x600 [22]
o configure: use icc options without space [21]
o test1112: Increase the timeout from 7s to 16s [20]
o SCP: upload speed on a fast connection limited to 16384 B/s
o curl_setup_once: fix errno access for lwip on Windows [24]
o HTTP: Output http response 304 when modified time is too old [23]
This release includes the following known bugs:
@@ -72,34 +71,41 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and
advice from friends like these:
Alex Vinnik, Alessandro Ghedini, Nick Zitzmann, Kamil Dudka,
Lluis Batlle i Rossell, Nach M. S., Kim Vandry, Ben Greear, Dan Fandrich,
Dave Reisner, Evgeny Turnaev, Guenter Knauf, John E. Malmberg, Marc Hoersken,
Patrick Monnerat, Sergei Nikulov, Yang Tse, Andreas Malzahn, Clemens Gruber,
Jean-Noel Rouvignac, Markus Moeller, Fabian Keil, Dagobert Michelsen,
Byrial Jensen, Justin Karneges, Edward Rudd, Marc Doughty, Konstantin Isakov,
Alex McLellan, Bill Doyle, Colby Ranger, Fabian Keil, Gisle Vanem,
John E. Malmberg, Jonathan Nieder, Kamil Dudka, Shawn Landden,
Tor Arntsen, Will Dietz, Yi Huang, Kyle L. Huff, Steve Holme, Mike Mio,
Stefan Neis, Nick Zitzmann, Geoff Beier, John Dunn, Jiri Hruska,
Tomas Mlcoch, Kim Vandry, Ben Greear, Gorilla Maguila, Jerry Krinock,
Yamada Yasuharu, Gordon Marler, Dave Thompson, D. Flinkmann,
Benoit Sigoure, Clemens Gruber, Guenter Knauf, Petr Pisar, Elmira A Semenova,
Francois Charlier, Ishan SinghLevett, Marcel Raad, Ulf Samuelsson,
Andrej E Baranov, Derek Higgins, Heinrich Schaefer
Thanks! (and sorry if I forgot to mention someone)
References to bug reports and discussions on issues:
[1] = http://curl.haxx.se/bug/view.cgi?id=1200
[2] = http://curl.haxx.se/bug/view.cgi?id=1180
[3] = http://curl.haxx.se/bug/view.cgi?id=1249
[4] = http://curl.haxx.se/bug/view.cgi?id=1191
[5] = http://curl.haxx.se/bug/view.cgi?id=1251
[6] = http://curl.haxx.se/mail/archive-2013-06/0052.html
[7] = http://curl.haxx.se/bug/view.cgi?id=1252
[8] = http://curl.haxx.se/mail/lib-2013-07/0046.html
[9] = http://curl.haxx.se/mail/lib-2013-07/0115.html
[10] = http://curl.haxx.se/mail/lib-2013-07/0103.html
[11] = http://curl.haxx.se/bug/view.cgi?id=496
[12] = http://curl.haxx.se/bug/view.cgi?id=1217
[13] = http://curl.haxx.se/mail/lib-2013-07/0258.html
[14] = http://curl.haxx.se/bug/view.cgi?id=758
[15] = http://curl.haxx.se/mail/lib-2013-07/0239.html
[16] = http://curl.haxx.se/bug/view.cgi?id=1255
[17] = http://curl.haxx.se/mail/archive-2013-07/0031.html
[18] = http://curl.haxx.se/bug/view.cgi?id=1262
[19] = http://curl.haxx.se/mail/lib-2013-08/0057.html
[1] = http://curl.haxx.se/mail/lib-2013-08/0043.html
[2] = http://bugs.debian.org/719856
[3] = http://daniel.haxx.se/blog/2013/08/20/testing-curl_multi_socket_action/
[4] = http://curl.haxx.se/bug/view.cgi?id=1269
[5] = https://github.com/bagder/curl/pull/76
[6] = http://curl.haxx.se/mail/lib-2013-08/0211.html
[7] = http://curl.haxx.se/bug/view.cgi?id=1264
[8] = http://curl.haxx.se/bug/view.cgi?id=1267
[9] = http://curl.haxx.se/mail/lib-2013-08/0234.html
[10] = http://curl.haxx.se/mail/lib-2013-08/0136.html
[11] = https://bugzilla.redhat.com/1005686
[12] = http://curl.haxx.se/mail/lib-2013-08/0109.html
[13] = http://curl.haxx.se/bug/view.cgi?id=1273
[14] = http://curl.haxx.se/mail/lib-2013-08/0209.html
[15] = http://curl.haxx.se/mail/lib-2013-08/0265.html
[16] = http://curl.haxx.se/mail/lib-2013-08/0170.html
[17] = http://curl.haxx.se/bug/view.cgi?id=1278
[18] = http://curl.haxx.se/bug/view.cgi?id=1279
[19] = http://curl.haxx.se/bug/view.cgi?id=1281
[20] = http://curl.haxx.se/mail/lib-2010-02/0200.html
[21] = http://curl.haxx.se/mail/lib-2013-09/0182.html
[22] = http://curl.haxx.se/bug/view.cgi?id=1282
[23] = http://curl.haxx.se/bug/view.cgi?id=1288
[24] = http://curl.haxx.se/mail/lib-2013-10/0048.html

View File

@@ -2619,18 +2619,18 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
fi
capath="$want_capath"
ca="no"
elif test "x$cross_compiling" != "xyes"; then
dnl NOT cross-compiling and...
dnl neither of the --with-ca-* options are provided
else
dnl first try autodetecting a CA bundle , then a CA path
dnl both autodetections can be skipped by --without-ca-*
ca="no"
capath="no"
if test "x$cross_compiling" != "xyes"; then
dnl NOT cross-compiling and...
dnl neither of the --with-ca-* options are provided
if test "x$want_ca" = "xunset"; then
dnl the path we previously would have installed the curl ca bundle
dnl to, and thus we now check for an already existing cert in that place
dnl in case we find no other
dnl to, and thus we now check for an already existing cert in that
dnl place in case we find no other
if test "x$prefix" != xNONE; then
cac="${prefix}/share/curl/curl-ca-bundle.crt"
else
@@ -2662,6 +2662,7 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
dnl no option given and cross-compiling
AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling])
fi
fi
if test "x$ca" != "xno"; then
CURL_CA_BUNDLE='"'$ca'"'

View File

@@ -150,7 +150,6 @@ dnl initialize all the info variables
curl_ssl_msg="no (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )"
curl_ssh_msg="no (--with-libssh2)"
curl_zlib_msg="no (--with-zlib)"
curl_krb4_msg="no (--with-krb4*)"
curl_gss_msg="no (--with-gssapi)"
curl_spnego_msg="no (--with-spnego)"
curl_tls_srp_msg="no (--enable-tls-srp)"
@@ -1134,101 +1133,6 @@ no)
;;
esac
dnl **********************************************************************
dnl Check for the presence of Kerberos4 libraries and headers
dnl **********************************************************************
AC_ARG_WITH(krb4-includes,
AC_HELP_STRING([--with-krb4-includes=DIR],
[Specify location of kerberos4 headers]),[
CPPFLAGS="$CPPFLAGS -I$withval"
KRB4INC="$withval"
want_krb4=yes
])
AC_ARG_WITH(krb4-libs,
AC_HELP_STRING([--with-krb4-libs=DIR],[Specify location of kerberos4 libs]),[
LDFLAGS="$LDFLAGS -L$withval"
KRB4LIB="$withval"
want_krb4=yes
])
OPT_KRB4=off
AC_ARG_WITH(krb4,dnl
AC_HELP_STRING([--with-krb4=DIR],[where to look for Kerberos4]),[
OPT_KRB4="$withval"
if test X"$OPT_KRB4" != Xno; then
want_krb4="yes"
if test X"$OPT_KRB4" != Xyes; then
LDFLAGS="$LDFLAGS -L$OPT_KRB4/lib$libsuff"
KRB4LIB="$OPT_KRB4/lib$libsuff"
CPPFLAGS="$CPPFLAGS -I$OPT_KRB4/include"
KRB4INC="$OPT_KRB4/include"
fi
fi
])
AC_MSG_CHECKING([if Kerberos4 support is requested])
if test "$want_krb4" = yes
then
if test "$ipv6" = "yes"; then
echo krb4 is not compatible with IPv6
exit 1
fi
AC_MSG_RESULT(yes)
dnl Check for & handle argument to --with-krb4
AC_MSG_CHECKING(where to look for Kerberos4)
if test X"$OPT_KRB4" = Xyes
then
AC_MSG_RESULT([defaults])
else
AC_MSG_RESULT([libs in $KRB4LIB, headers in $KRB4INC])
fi
dnl Check for DES library
AC_CHECK_LIB(des, des_pcbc_encrypt,
[
AC_CHECK_HEADERS(des.h)
dnl resolv lib?
AC_CHECK_FUNC(res_search, , [AC_CHECK_LIB(resolv, res_search)])
dnl Check for the Kerberos4 library
AC_CHECK_LIB(krb, krb_net_read,
[
dnl Check for header files
AC_CHECK_HEADERS(krb.h)
dnl we found the required libraries, add to LIBS
LIBS="-lkrb -lcom_err -ldes $LIBS"
dnl Check for function krb_get_our_ip_for_realm
dnl this is needed for NAT networks
AC_CHECK_FUNCS(krb_get_our_ip_for_realm)
dnl add define KRB4
AC_DEFINE(HAVE_KRB4, 1,
[if you have the Kerberos4 libraries (including -ldes)])
dnl substitute it too!
KRB4_ENABLED=1
AC_SUBST(KRB4_ENABLED)
curl_krb4_msg="enabled"
dnl the krb4 stuff needs a strlcpy()
AC_CHECK_FUNCS(strlcpy)
])
])
else
AC_MSG_RESULT(no)
fi
dnl **********************************************************************
dnl Check for FBopenssl(SPNEGO) libraries
dnl **********************************************************************
@@ -2808,6 +2712,92 @@ dnl http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/ \
dnl genprogc/thread_quick_ref.htm
dnl **********************************************************************
dnl Check for nghttp2
dnl **********************************************************************
AC_MSG_CHECKING([whether to build with nghttp2])
OPT_H2="no"
AC_ARG_WITH(nghttp2,
AC_HELP_STRING([--with-nghttp2=PATH],[Enable nghttp2 usage])
AC_HELP_STRING([--without-nghttp2],[Disable nghttp2 usage]),
[OPT_H2=$withval])
case "$OPT_H2" in
no)
dnl --without-nghttp2 option used
want_idn="no"
AC_MSG_RESULT([no])
;;
default)
dnl configure option not specified
want_h2="no"
want_h2_path="default"
AC_MSG_RESULT([no])
;;
yes)
dnl --with-nghttp2 option used without path
want_h2="yes"
want_h2_path=""
AC_MSG_RESULT([yes])
;;
*)
dnl --with-nghttp2 option used with path
want_h2="yes"
want_h2_path="$withval"
AC_MSG_RESULT([yes ($withval)])
;;
esac
curl_h2_msg="disabled (--with-nghttp2)"
if test X"$OPT_H2" != Xno; then
dnl backup the pre-librtmp variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
h2pcdir=${want_h2_path}/lib/pkgconfig
CURL_CHECK_PKGCONFIG(libnghttp2, $h2pcdir)
if test "$PKGCONFIG" != "no" ; then
LIB_H2=`CURL_EXPORT_PCDIR([$h2pcdir])
$PKGCONFIG --libs-only-l libnghttp2`
AC_MSG_NOTICE([-l is $LIB_H2])
CPP_H2=`CURL_EXPORT_PCDIR([$h2pcdir]) dnl
$PKGCONFIG --cflags-only-I libnghttp2`
AC_MSG_NOTICE([-I is $CPP_H2])
LD_H2=`CURL_EXPORT_PCDIR([$h2pcdir])
$PKGCONFIG --libs-only-L libnghttp2`
AC_MSG_NOTICE([-L is $LD_H2])
else
dnl To avoid link errors, we do not allow --libnghttp2 without
dnl a pkgconfig file
AC_MSG_ERROR([--with-nghttp2 was specified but could not find libnghttp2 pkg-config file.])
fi
LDFLAGS="$LDFLAGS $LD_H2"
CPPFLAGS="$CPPFLAGS $CPP_H2"
LIBS="$LIB_H2 $LIBS"
AC_CHECK_LIB(nghttp2, nghttp2_session_client_new,
[
AC_CHECK_HEADERS(nghttp2/nghttp2.h,
curl_h2_msg="enabled (nghttp2)"
NGHTTP2_ENABLED=1
AC_DEFINE(USE_NGHTTP2, 1, [if nghttp2 is in use])
AC_SUBST(USE_NGHTTP2, [1])
)
],
dnl not found, revert back to clean variables
LDFLAGS=$CLEANLDFLAGS
CPPFLAGS=$CLEANCPPFLAGS
LIBS=$CLEANLIBS
)
fi
dnl **********************************************************************
dnl Back to "normal" configuring
dnl **********************************************************************
@@ -3365,9 +3355,6 @@ if test "x$USE_SSLEAY" = "x1"; then
elif test -n "$SSL_ENABLED"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES SSL"
fi
if test "@KRB4_ENABLED@" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES KRB4"
fi
if test "x$IPV6_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
fi
@@ -3397,6 +3384,10 @@ if test "x$USE_TLS_SRP" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi
if test "x$USE_NGHTTP2" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi
AC_SUBST(SUPPORT_FEATURES)
dnl For supported protocols in pkg-config file
@@ -3542,7 +3533,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
SSL support: ${curl_ssl_msg}
SSH support: ${curl_ssh_msg}
zlib support: ${curl_zlib_msg}
krb4 support: ${curl_krb4_msg}
GSSAPI support: ${curl_gss_msg}
SPNEGO support: ${curl_spnego_msg}
TLS-SRP support: ${curl_tls_srp_msg}
@@ -3561,6 +3551,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
RTSP support: ${curl_rtsp_msg}
RTMP support: ${curl_rtmp_msg}
metalink support: ${curl_mtlnk_msg}
HTTP2 support: ${curl_h2_msg}
Protocols: ${SUPPORT_PROTOCOLS}
])

46
contributors.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 2013, 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.
#
###########################################################################
#
# This script shows all mentioned contributors from <hash> until HEAD. To aid
# when writing RELEASE-NOTES and THANKS.
#
start=$1
if test -z "$start"; then
echo "Usage: $0 <since this tag/hash>"
fi
# filter out Author:, Commit: and *by: lines
# cut off the email parts
# cut off spaces first and last on the line
# only count names with a space (ie more than one word)
# sort all unique names
git log $start..HEAD | \
egrep '(Author|Commit|by):' | \
cut -d: -f2- | \
cut '-d<' -f1 | \
sed -e 's/^ //' -e 's/ $//g' | \
grep ' ' | \
sort -u

102
docs/FAQ
View File

@@ -202,27 +202,25 @@ FAQ
better. We do however believe in a few rules when it comes to the future of
curl:
* Curl -- the command line tool -- is to remain a non-graphical command line
tool. If you want GUIs or fancy scripting capabilities, you should look
for another tool that uses libcurl.
Curl -- the command line tool -- is to remain a non-graphical command line
tool. If you want GUIs or fancy scripting capabilities, you should look for
another tool that uses libcurl.
* We do not add things to curl that other small and available tools already
do very fine at the side. Curl's output is fine to pipe into another
program or redirect to another file for the next program to interpret.
We do not add things to curl that other small and available tools already do
very fine at the side. Curl's output is fine to pipe into another program or
redirect to another file for the next program to interpret.
* We focus on protocol related issues and improvements. If you wanna do more
magic with the supported protocols than curl currently does, chances are
big we will agree. If you wanna add more protocols, we may very well
agree.
We focus on protocol related issues and improvements. If you wanna do more
magic with the supported protocols than curl currently does, chances are big
we will agree. If you wanna add more protocols, we may very well agree.
* If you want someone else to make all the work while you wait for us to
If you want someone else to make all the work while you wait for us to
implement it for you, that is not a very friendly attitude. We spend a
considerable time already on maintaining and developing curl. In order to
get more out of us, you should consider trading in some of your time and
efforts in return.
* If you write the code, chances are bigger that it will get into curl
faster.
If you write the code, chances are bigger that it will get into curl faster.
1.5 Who makes curl?
@@ -263,7 +261,7 @@ FAQ
Our project name curl has been in effective use since 1998. We were not the
first computer related project to use the name "curl" and do not claim any
first-hand rights to the name.
rights to the name.
We recognize that we will be living in parallel with curl.com and wish them
every success.
@@ -620,15 +618,15 @@ FAQ
Some workarounds usually suggested to overcome this Javascript dependency:
- Depending on the Javascript complexity, write up a script that
translates it to another language and execute that.
Depending on the Javascript complexity, write up a script that translates it
to another language and execute that.
- Read the Javascript code and rewrite the same logic in another language.
Read the Javascript code and rewrite the same logic in another language.
- Implement a Javascript interpreter, people have successfully used the
Implement a Javascript interpreter, people have successfully used the
Mozilla Javascript engine in the past.
- Ask your admins to stop this, for a static proxy setup or similar.
Ask your admins to stop this, for a static proxy setup or similar.
3.15 Can I do recursive fetches with curl?
@@ -644,23 +642,27 @@ FAQ
There are three different kinds of "certificates" to keep track of when we
talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl.
- Client certificate. The server you communicate may require that you can
provide this in order to prove that you actually are who you claim to be.
If the server doesn't require this, you don't need a client certificate.
CLIENT CERTIFICATE
The server you communicate may require that you can provide this in order to
prove that you actually are who you claim to be. If the server doesn't
require this, you don't need a client certificate.
A client certificate is always used together with a private key, and the
private key has a pass phrase that protects it.
- Server certificate. The server you communicate with has a server
certificate. You can and should verify this certificate to make sure that
you are truly talking to the real server and not a server impersonating
it.
SERVER CERTIFICATE
- Certificate Authority certificate ("CA cert"). You often have several CA
certs in a CA cert bundle that can be used to verify a server certificate
that was signed by one of the authorities in the bundle. curl does not
come with a CA cert bundle but most curl installs provide one. You can
also override the default.
The server you communicate with has a server certificate. You can and should
verify this certificate to make sure that you are truly talking to the real
server and not a server impersonating it.
CERTIFICATE AUTHORITY CERTIFICATE ("CA cert")
You often have several CA certs in a CA cert bundle that can be used to
verify a server certificate that was signed by one of the authorities in the
bundle. curl does not come with a CA cert bundle but most curl installs
provide one. You can also override the default.
The server certificate verification process is made by using a Certificate
Authority certificate ("CA cert") that was used to sign the server
@@ -669,9 +671,9 @@ FAQ
4.12 and the SSLCERTS document
(http://curl.haxx.se/docs/sslcerts.html). Server certificates that are
"self-signed" or otherwise signed by a CA that you do not have a CA cert
for, cannot be verified. If the verification during a connect fails, you
are refused access. You then need to explicitly disable the verification
to connect to the server.
for, cannot be verified. If the verification during a connect fails, you are
refused access. You then need to explicitly disable the verification to
connect to the server.
3.17 How do I list the root dir of an FTP server?
@@ -794,12 +796,13 @@ FAQ
curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl'
In Windows, the standard DOS shell treats the %-symbol specially and you
need to use TWO %-symbols for each single one you want to use in the URL.
In Windows, the standard DOS shell treats the percent sign specially and you
need to use TWO percent signs for each single one you want to use in the
URL.
Also note that if you want the literal %-symbol to be part of the data you
pass in a POST using -d/--data you must encode it as '%25' (which then also
needs the %-symbol doubled on Windows machines).
If you want a literal percent sign to be part of the data you pass in a POST
using -d/--data you must encode it as '%25' (which then also needs the
percent sign doubled on Windows machines).
4.3 How can I use {, }, [ or ] to specify multiple URLs?
@@ -968,13 +971,13 @@ FAQ
4.14 Redirects work in browser but not with curl!
curl supports HTTP redirects fine (see item 3.8). Browsers generally support
at least two other ways to perform directs that curl does not:
at least two other ways to perform redirects that curl does not:
- Meta tags. You can write a HTML tag that will cause the browser to
redirect to another given URL after a certain time.
Meta tags. You can write a HTML tag that will cause the browser to redirect
to another given URL after a certain time.
- Javascript. You can write a Javascript program embedded in a HTML page
that redirects the browser to another given URL.
Javascript. You can write a Javascript program embedded in a HTML page that
redirects the browser to another given URL.
There is no way to make curl follow these redirects. You must either
manually figure out what the page is set to do, or you write a script that
@@ -1270,17 +1273,18 @@ FAQ
5.12 Can I make libcurl fake or hide my real IP address?
No. libcurl operates on a higher level than so. Besides, faking IP address
would imply sending IP packages with a made-up source address, and then you
normally get a problem with intercepting the packages sent back as they
would then not be routed to you!
No. libcurl operates on a higher level. Besides, faking IP address would
imply sending IP packet with a made-up source address, and then you normally
get a problem with receiving the packet sent back as they would then not be
routed to you!
If you use a proxy to access remote sites, the sites will not see your local
IP address but instead the address of the proxy.
Also note that on many networks NATs or other IP-munging techniques are used
that makes you see and use a different IP address locally than what the
remote server will see you coming from.
remote server will see you coming from. You may also consider using
http://www.torproject.org .
5.13 How do I stop an ongoing transfer?

View File

@@ -3,6 +3,9 @@ join in and help us correct one or more of these! Also be sure to check the
changelog of the current development status, as one or more of these problems
may have been fixed since this was written!
84. CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
backends, so relying on this information in a generic app is flaky.
83. curl is unable to load non-default openssl engines, because openssl isn't
initialized properly. This seems to require OpenSSL_config() or
CONF_modules_load_file() to be used by libcurl but the first seems to not
@@ -24,18 +27,18 @@ may have been fixed since this was written!
80. Curl doesn't recognize certificates in DER format in keychain, but it
works with PEM.
http://curl.haxx.se/bug/view.cgi?id=3439999
http://curl.haxx.se/bug/view.cgi?id=1065
79. SMTP. When sending data to multiple recipients, curl will abort and return
failure if one of the recipients indicate failure (on the "RCPT TO"
command). Ordinary mail programs would proceed and still send to the ones
that can receive data. This is subject for change in the future.
http://curl.haxx.se/bug/view.cgi?id=3438362
http://curl.haxx.se/bug/view.cgi?id=1116
78. curl and libcurl don't always signal the client properly when "sending"
zero bytes files - it makes for example the command line client not creating
any file at all. Like when using FTP.
http://curl.haxx.se/bug/view.cgi?id=3438362
http://curl.haxx.se/bug/view.cgi?id=1063
77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it
"abuses" the underlying connection re-use system and if connections are
@@ -50,7 +53,7 @@ may have been fixed since this was written!
properly if built with UNICODE defined together with the schannel/winssl
backend. The original problem was mentioned in:
http://curl.haxx.se/mail/lib-2009-10/0024.html
http://curl.haxx.se/bug/view.cgi?id=2944325
http://curl.haxx.se/bug/view.cgi?id=896
The schannel version verified to work as mentioned in
http://curl.haxx.se/mail/lib-2012-07/0073.html
@@ -60,7 +63,7 @@ may have been fixed since this was written!
acknowledge the connection timeout during that phase but only the "real"
timeout - which may surprise users as it is probably considered to be the
connect phase to most people. Brought up (and is being misunderstood) in:
http://curl.haxx.se/bug/view.cgi?id=2844077
http://curl.haxx.se/bug/view.cgi?id=856
72. "Pausing pipeline problems."
http://curl.haxx.se/mail/lib-2009-07/0214.html
@@ -78,7 +81,7 @@ may have been fixed since this was written!
http://tools.ietf.org/html/draft-reschke-rfc2231-in-http-02
66. When using telnet, the time limitation options don't work.
http://curl.haxx.se/bug/view.cgi?id=2818950
http://curl.haxx.se/bug/view.cgi?id=846
65. When doing FTP over a socks proxy or CONNECT through HTTP proxy and the
multi interface is used, libcurl will fail if the (passive) TCP connection
@@ -109,7 +112,7 @@ may have been fixed since this was written!
and instead the connection is "cancelled" (the operation is considered done)
prematurely. There is a half-baked (busy-looping) patch provided in the bug
report but it cannot be accepted as-is. See
http://curl.haxx.se/bug/view.cgi?id=2006544
http://curl.haxx.se/bug/view.cgi?id=748
55. libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's
library header files exporting symbols/macros that should be kept private
@@ -133,12 +136,12 @@ may have been fixed since this was written!
protocol code. This should be very rare.
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=649
41. When doing an operation over FTP that requires the ACCT command (but not
when logging in), the operation will fail since libcurl doesn't detect this
and thus fails to issue the correct command:
http://curl.haxx.se/bug/view.cgi?id=1693337
http://curl.haxx.se/bug/view.cgi?id=635
39. Steffen Rumler's Race Condition in Curl_proxyCONNECT:
http://curl.haxx.se/mail/lib-2007-01/0045.html
@@ -151,7 +154,7 @@ may have been fixed since this was written!
34. The SOCKS4 connection codes don't properly acknowledge (connect) timeouts.
Also see #12. According to bug #1556528, even the SOCKS5 connect code does
not do it right: http://curl.haxx.se/bug/view.cgi?id=1556528,
not do it right: http://curl.haxx.se/bug/view.cgi?id=604
31. "curl-config --libs" will include details set in LDFLAGS when configure is
run that might be needed only for building libcurl. Further, curl-config
@@ -166,13 +169,12 @@ may have been fixed since this was written!
IDs in URLs to get around the problem of percent signs being
special. According to the reporter, Firefox deals with the URL _with_ a
percent letter (which seems like a blatant URL spec violation).
libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25).
See http://curl.haxx.se/bug/view.cgi?id=1371118
libcurl supports zone IDs where the percent sign is URL-escaped (i.e. %25):
http://curl.haxx.se/bug/view.cgi?id=555
26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in
"system context" will make it use wrong(?) user name - at least when compared
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=535
23. SOCKS-related problems:
B) libcurl doesn't support FTPS over a SOCKS proxy.
@@ -218,7 +220,7 @@ may have been fixed since this was written!
10. To get HTTP Negotiate authentication to work fine, you need to provide a
(fake) user name (this concerns both curl and the lib) because the code
wrongly only considers authentication if there's a user name provided.
http://curl.haxx.se/bug/view.cgi?id=1004841. How?
http://curl.haxx.se/bug/view.cgi?id=440 How?
http://curl.haxx.se/mail/lib-2004-08/0182.html
8. Doing resumed upload over HTTP does not work with '-C -', because curl

View File

@@ -103,6 +103,18 @@ any response data to the terminal.
If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your
friend.
.SH OPTIONS
Options start with one or two dashes. Many of the options require an addition
value next to it.
The short "single-dash" form of the options, -d for example, may be used with
or without a space between it and its value, although a space is a recommended
separator. The long "double-dash" form, --data for example, requires a space
between it and its value.
Short version options that don't need any additional values can be used
immediately next to each other, like for example you can specify all the
options -O, -L and -v at once as -OLv.
In general, all boolean options are enabled with --\fBoption\fP and yet again
disabled with --\fBno-\fPoption. That is, you use the exact same option name
but prefix it with "no-". However, in this list we mostly only list and show
@@ -113,8 +125,14 @@ same command line option.)
Make curl display progress as a simple progress bar instead of the standard,
more informational, meter.
.IP "-0, --http1.0"
(HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its
internally preferred: HTTP 1.1.
(HTTP) Tells curl to use HTTP version 1.0 instead of using its internally
preferred: HTTP 1.1.
.IP "--http1.1"
(HTTP) Tells curl to use HTTP version 1.1. This is the internal default
version. (Added in 7.33.0)
.IP "--http2.0"
(HTTP) Tells curl to issue its requests using HTTP 2.0. This requires that the
underlying libcurl was built to support it. (Added in 7.33.0)
.IP "-1, --tlsv1"
(SSL)
Forces curl to use TLS version 1 when negotiating with a remote TLS server.
@@ -272,7 +290,8 @@ If you start the data with the letter @, the rest should be a file name to
read the data from, or - if you want curl to read the data from stdin. The
contents of the file must already be URL-encoded. Multiple files can also be
specified. Posting data from a file named 'foobar' would thus be done with
\fI--data @foobar\fP.
\fI--data\fP @foobar. When --data is told to read from a file like that,
carriage returns and newlines will be stripped out.
.IP "-D, --dump-header <file>"
Write the protocol headers to the specified file.
@@ -294,7 +313,7 @@ whatsoever.
If you start the data with the letter @, the rest should be a filename. Data
is posted in a similar manner as \fI--data-ascii\fP does, except that newlines
are preserved and conversions are never done.
and carriage returns are preserved and conversions are never done.
If this option is used several times, the ones following the first will append
data as described in \fI-d, --data\fP.
@@ -369,6 +388,39 @@ 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 "--dns-interface <interface>"
Tell curl to send outgoing DNS requests through <interface>. This option
is a counterpart to \fI--interface\fP (which does not affect DNS). The
supplied string must be an interface name (not an address).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "--dns-ipv4-addr <ip-address>"
Tell curl to bind to <ip-address> when making IPv4 DNS requests, so that
the DNS requests originate from this address. The argument should be a
single IPv4 address.
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "--dns-ipv6-addr <ip-address>"
Tell curl to bind to <ip-address> when making IPv6 DNS requests, so that
the DNS requests originate from this address. The argument should be a
single IPv6 address.
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "--dns-servers <ip-address,ip-address>"
Set the list of DNS servers to be used instead of the system default.
The list of IP addresses should be separated with commas. Port numbers
may also optionally be given as \fI:<port-number>\fP after each IP
address.
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "-e, --referer <URL>"
(HTTP) Sends the "Referer Page" information to the HTTP server. This can also
be set with the \fI-H, --header\fP flag of course. When used with
@@ -380,7 +432,8 @@ If this option is used several times, the last one will be used.
.IP "-E, --cert <certificate[:password]>"
(SSL) Tells curl to use the specified client certificate file when getting a
file with HTTPS, FTPS or another SSL-based protocol. The certificate must be
in PEM format. If the optional password isn't specified, it will be queried
in PKCS#12 format if using Secure Transport, or PEM format if using any other
engine. If the optional password isn't specified, it will be queried
for on the terminal. Note that this option assumes a \&"certificate" file that
is the private key and the private certificate concatenated! See \fI--cert\fP
and \fI--key\fP to specify them independently.
@@ -396,9 +449,10 @@ recognized as password delimiter. If the nickname contains "\\", it needs to
be escaped as "\\\\" so that it is not recognized as an escape character.
(iOS and Mac OS X only) If curl is built against Secure Transport, then the
certificate string must match the name of a certificate that's in the system or
user keychain. The private key corresponding to the certificate, and
certificate chain (if any), must also be present in the keychain.
certificate string can either be the name of a certificate/private key in the
system or user keychain, or the path to a PKCS#12-encoded certificate and
private key. If you want to use a file from the current directory, please
precede it with "./" prefix, in order to avoid confusion with a nickname.
If this option is used several times, the last one will be used.
.IP "--engine <name>"
@@ -1000,6 +1054,14 @@ you want the file saved in a different directory, make sure you change current
working directory before you invoke curl with the \fB-O, --remote-name\fP flag!
You may use this option as many times as the number of URLs you have.
.IP "--oauth2-bearer"
(IMAP/POP3/SMTP) Specify the Bearer Token for OAUTH 2.0 server authentication.
The Bearer Token is used in conjuction with the user name which can be
specified as part of the \fI--url\fP or \fI-u, --user\fP options.
The Bearer Token and user name are formatted according to RFC 6750.
If this option is used several times, the last one will be used.
.IP "-p, --proxytunnel"
When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP
protocols to attempt to tunnel through the proxy instead of merely using it to
@@ -1473,16 +1535,23 @@ If this option is used several times, the last one will be used.
.IP "--trace-time"
Prepends a time stamp to each trace or verbose line that curl displays.
(Added in 7.14.0)
.IP "-u, --user <user:password>"
Specify the user name and password to use for server authentication. Overrides
\fI-n, --netrc\fP and \fI--netrc-optional\fP.
.IP "-u, --user <user:password;options>"
Specify the user name, password and optional login options to use for server
authentication. Overrides \fI-n, --netrc\fP and \fI--netrc-optional\fP.
If you just give the user name (without entering a colon) curl will prompt for
a password.
If you simply specify the user name, with or without the login options, curl
will prompt for a password.
If you use an SSPI-enabled curl binary and do NTLM authentication, you can
force curl to pick up the user name and password from your environment by
simply specifying a single colon with this option: "-u :".
If you use an SSPI-enabled curl binary and perform NTLM authentication, you
can force curl to select the user name and password from your environment by
simply specifying a single colon with this option: "-u :" or by specfying the
login options on their own, for example "-u ;auth=NTLM".
You can use the optional login options part to specify protocol specific
options that may be used during authentication. At present only IMAP, POP3 and
SMTP support login options as part of the user login information. For more
information about the login options please see RFC 2384, RFC 5092 and IETF
draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
If this option is used several times, the last one will be used.
.IP "-U, --proxy-user <user:password>"
@@ -1643,8 +1712,16 @@ to follow location: headers.
If this option is used several times, the last one will be used.
.IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>"
Use the specified HTTP proxy. If the port number is not specified, it is
assumed at port 1080.
Use the specified proxy.
The proxy string can be specified with a protocol:// prefix to specify
alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
socks5h:// to request the specific SOCKS version to be used. No protocol
specified, http:// and all others will be treated as HTTP proxies. (The
protocol support was added in curl 7.21.7)
If the port number is not specified in the proxy string, it is assumed to be
1080.
This option overrides existing environment variables that set the proxy to
use. If there's an environment variable setting a proxy, you can set proxy to
@@ -1663,11 +1740,6 @@ The proxy host can be specified the exact same way as the proxy environment
variables, including the protocol prefix (http://) and the embedded user +
password.
From 7.21.7, the proxy string may be specified with a protocol:// prefix to
specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
socks5h:// to request the specific SOCKS version to be used. No protocol
specified, http:// and all others will be treated as HTTP proxies.
If this option is used several times, the last one will be used.
.IP "-X, --request <command>"
(HTTP) Specifies a custom request method to use when communicating with the

View File

@@ -5,7 +5,7 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
persistant post-callback postit2 sepheaders simple simplepost simplessl \
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \
progressfunc pop3s pop3slist imap url2file sftpget ftpsget
progressfunc pop3s pop3slist imap url2file sftpget ftpsget postinmemory
# These examples require external dependencies that may not be commonly
# available on POSIX systems, so don't bother attempting to compile them here.

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -98,10 +98,6 @@ int main(void)
* bytes big and contains the remote file.
*
* Do something nice with it!
*
* You should be aware of the fact that at this point we might have an
* allocated data block, and nothing has yet deallocated that data. So when
* you're done with it, you should free() it as a nice application.
*/
printf("%lu bytes retrieved\n", (long)chunk.size);

View File

@@ -0,0 +1,111 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, 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.
*
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if(mem->memory == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
int main(void)
{
CURL *curl;
CURLcode res;
struct MemoryStruct chunk;
static const char *postthis="Field=1&Field=2&Field=3";
chunk.memory = malloc(1); /* will be grown as needed by realloc above */
chunk.size = 0; /* no data at this point */
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.org/");
/* send all data to this function */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
/* some servers don't like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
/* if we don't provide POSTFIELDSIZE, libcurl will strlen() by
itself */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else {
/*
* Now, our chunk.memory points to a memory block that is chunk.size
* bytes big and contains the remote file.
*
* Do something nice with it!
*/
printf("%s\n",chunk.memory);
}
/* always cleanup */
curl_easy_cleanup(curl);
if(chunk.memory)
free(chunk.memory);
/* we're done with libcurl, so clean it up */
curl_global_cleanup();
}
return 0;
}

View File

@@ -38,8 +38,11 @@ that returns pause signals to the library that it couldn't take care of any
data at all, and that data will then be delivered again to the callback when
the writing is later unpaused.
NOTE: while it may feel tempting, take care and notice that you cannot call
this function from another thread.
While it may feel tempting, take care and notice that you cannot call this
function from another thread. To unpause, you may for example call it from the
progress callback (see \fIcurl_easy_setopt(3)\fP's
\fICURLOPT_PROGRESSFUNCTION\fP), which gets called at least once per second,
even if the connection is paused.
When this function is called to unpause reading, the chance is high that you
will get your write callback called before this function returns.

View File

@@ -260,9 +260,9 @@ used to fast forward a file in a resumed upload (instead of reading all
uploaded bytes with the normal read function/callback). It is also called to
rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication
method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET,
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl
only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on
success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
SEEK_CUR and SEEK_END as argument for origin, although libcurl currently only
passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on success, 1
(CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
(CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is
free to work around the problem if possible. The latter can sometimes be done
by instead reading from the input or similar.
@@ -891,6 +891,19 @@ Active Directory server.
For more information about the individual components of a LDAP URL please
see RFC4516.
.B RTMP
There's no official URL spec for RTMP so libcurl uses the URL syntax supported
by the underlying librtmp library. It has a syntax where it wants a
traditional URL, followed by a space and a series of space-separated
name=value pairs.
While space is not typically a "legal" letter, libcurl accepts them. When a
user wants to pass in a '#' (hash) character it will be treated as a fragment
and get cut off by libcurl if provided literally. You will instead have to
escape it by providing it as backslash and its ASCII value in hexadecimal:
"\\23".
.B NOTES
Starting with version 7.20.0, the fragment part of the URI will not be sent as
@@ -1289,6 +1302,13 @@ mechanisms and to the IMAP, POP3 and SMTP protocols. (Added in 7.31.0)
Note: Whilst IMAP supports this option there is no need to explicitly set it,
as libcurl can determine the feature itself when the server supports the
SASL-IR CAPABILITY.
.IP CURLOPT_BEARER
Pass a char * as parameter, which should point to the zero terminated OAUTH
2.0 Bearer Access Token for use with IMAP. POP3 and SMTP servers that support
the OAUTH 2.0 Authorization Framework. (Added in 7.33.0)
Note: The user name used to generate the Bearer Token should be supplied via
the \fICURLOPT_USERNAME\fP option.
.SH HTTP OPTIONS
.IP CURLOPT_AUTOREFERER
Pass a parameter set to 1 to enable this. When enabled, libcurl will
@@ -2142,10 +2162,14 @@ In unix-like systems, this might cause signals to be used unless
Default timeout is 0 (zero) which means it never times out.
.IP CURLOPT_TIMEOUT_MS
Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If
libcurl is built to use the standard system name resolver, that portion
of the transfer will still use full-second resolution for timeouts with
a minimum timeout allowed of one second.
An alternative to \fICURLOPT_TIMEOUT\fP but takes number of milliseconds
instead. If libcurl is built to use the standard system name resolver, that
portion of the transfer will still use full-second resolution for timeouts
with a minimum timeout allowed of one second.
If both \fICURLOPT_TIMEOUT\fP and \fICURLOPT_TIMEOUT_MS\fP are set, the value
set last will be used.
(Added in 7.16.2)
.IP CURLOPT_LOW_SPEED_LIMIT
Pass a long as parameter. It contains the transfer speed in bytes per second
@@ -2291,6 +2315,36 @@ This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.24.0)
.IP CURLOPT_DNS_INTERFACE
Pass a char * as parameter. Set the name of the network interface that
the DNS resolver should bind to. This must be an interface name (not an
address). Set this option to NULL to use the default setting (don't
bind to a specific interface).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.33.0)
.IP CURLOPT_DNS_LOCAL_IP4
Set the local IPv4 address that the resolver should bind to. The argument
should be of type char * and contain a single IPv4 address as a string.
Set this option to NULL to use the default setting (don't
bind to a specific IP address).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.33.0)
.IP CURLOPT_DNS_LOCAL_IP6
Set the local IPv6 address that the resolver should bind to. The argument
should be of type char * and contain a single IPv6 address as a string.
Set this option to NULL to use the default setting (don't
bind to a specific IP address).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.33.0)
.IP CURLOPT_ACCEPTTIMEOUT_MS
Pass a long telling libcurl the maximum number of milliseconds to wait for a
server to connect back to libcurl when an active FTP connection is used. If no
@@ -2298,22 +2352,20 @@ timeout is set, the internal default of 60000 will be used. (Added in 7.24.0)
.SH SSL and SECURITY OPTIONS
.IP CURLOPT_SSLCERT
Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your certificate. The default format is "PEM" and can be
changed with \fICURLOPT_SSLCERTTYPE\fP.
the file name of your certificate. The default format is "P12" on Secure
Transport and "PEM" on other engines, and can be changed with
\fICURLOPT_SSLCERTTYPE\fP.
With NSS this can also be the nickname of the certificate you wish to
authenticate with. If you want to use a file from the current directory, please
precede it with "./" prefix, in order to avoid confusion with a nickname.
(iOS and Mac OS X only) With Secure Transport, this string must match the name
of a certificate that's in the system or user keychain. You should encode this
string in UTF-8 format in case it contains non-ASCII characters. The private
key corresponding to the certificate, and certificate chain (if any), must
also be present in the keychain. (Added in 7.31.0)
With NSS or Secure Transport, this can also be the nickname of the certificate
you wish to authenticate with as it is named in the security database. If you
want to use a file from the current directory, please precede it with "./"
prefix, in order to avoid confusion with a nickname.
.IP CURLOPT_SSLCERTTYPE
Pass a pointer to a zero terminated string as parameter. The string should be
the format of your certificate. Supported formats are "PEM" and "DER". (Added
in 7.9.3)
the format of your certificate. Supported formats are "PEM" and "DER", except
with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
(on iOS 5 or later, or OS X 10.6 or later) also support "P12" for
PKCS#12-encoded files. (Added in 7.9.3)
.IP CURLOPT_SSLKEY
Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your private key. The default format is "PEM" and can be
@@ -2321,7 +2373,7 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
(iOS and Mac OS X only) This option is ignored if curl was built against Secure
Transport. Secure Transport expects the private key to be already present in
the keychain containing the certificate.
the keychain or PKCS#12 file containing the certificate.
.IP CURLOPT_SSLKEYTYPE
Pass a pointer to a zero terminated string as parameter. The string should be
the format of your private key. Supported formats are "PEM", "DER" and "ENG".

View File

@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2013, 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
@@ -273,6 +273,9 @@ The passed-in socket is not a valid one that libcurl already knows about.
.IP "CURLM_UNKNOWN_OPTION (6)"
curl_multi_setopt() with unsupported option
(Added in 7.15.4)
.IP "CURLM_ADDED_ALREADY (7)"
An easy handle already added to a multi handle was attempted to get added a
second time. (Added in 7.32.1)
.SH "CURLSHcode"
The "share" interface will return a CURLSHcode to indicate when an error has
occurred. Also consider \fIcurl_share_strerror(3)\fP.

View File

@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2013, 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
@@ -39,8 +39,15 @@ maintain while using libcurl. This essentially means you call
for details.
To transfer files, you always set up an "easy handle" using
\fIcurl_easy_init(3)\fP, but when you want the file(s) transferred you have
the option of using the "easy" interface, or the "multi" interface.
\fIcurl_easy_init(3)\fP for a single specific transfer (in either
direction). You then set your desired set of options in that handle with
\fIcurk_easy_setopt(3)\fP. Options you set with \fIcurl_easy_setopt(3)\fP will
be used on every repeated use of this handle until you either call the
function again and change the option, or you reset them all with
\fIcurl_easy_reset(3)\fP.
To actually transfer data you have the option of using the "easy" interface,
or the "multi" interface.
The easy interface is a synchronous interface with which you call
\fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is
@@ -51,7 +58,8 @@ The multi interface on the other hand is an asynchronous interface, that you
call and that performs only a little piece of the transfer on each invoke. It
is perfect if you want to do things while the transfer is in progress, or
similar. The multi interface allows you to select() on libcurl action, and
even to easily download multiple files simultaneously using a single thread. See further details in the \fIlibcurl-multi(3)\fP man page.
even to easily download multiple files simultaneously using a single
thread. See further details in the \fIlibcurl-multi(3)\fP man page.
You can have multiple easy handles share certain data, even if they are used
in different threads. This magic is setup using the share interface, as
@@ -115,19 +123,21 @@ Persistent connections means that libcurl can re-use the same connection for
several transfers, if the conditions are right.
libcurl will \fBalways\fP attempt to use persistent connections. Whenever you
use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP, libcurl will
attempt to use an existing connection to do the transfer, and if none exists
it'll open a new one that will be subject for re-use on a possible following
call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP.
use \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP etc, libcurl
will attempt to use an existing connection to do the transfer, and if none
exists it'll open a new one that will be subject for re-use on a possible
following call to \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP.
To allow libcurl to take full advantage of persistent connections, you should
do as many of your file transfers as possible using the same curl handle. When
you call \fIcurl_easy_cleanup(3)\fP, all the possibly open connections held by
libcurl will be closed and forgotten.
do as many of your file transfers as possible using the same handle.
Note that the options set with \fIcurl_easy_setopt(3)\fP will be used on
every repeated \fIcurl_easy_perform(3)\fP call.
If you use the easy interface, and you call \fIcurl_easy_cleanup(3)\fP, all
the possibly open connections held by libcurl will be closed and forgotten.
When you've created a multi handle and are using the multi interface, the
connection pool is instead kept in the multi handle so closing and creating
new easy handles to do transfers will not affect them. Instead all added easy
handles can take advantage of the single shared pool.
.SH "GLOBAL CONSTANTS"
There are a variety of constants that libcurl uses, mainly through its
internal use of other libraries, which are too complicated for the

View File

@@ -85,8 +85,8 @@ CURLE_LDAP_SEARCH_FAILED 7.1
CURLE_LIBRARY_NOT_FOUND 7.1 7.17.0
CURLE_LOGIN_DENIED 7.13.1
CURLE_MALFORMAT_USER 7.1 7.17.0
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
CURLE_NOT_BUILT_IN 7.21.5
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
CURLE_OK 7.1
CURLE_OPERATION_TIMEDOUT 7.10.2
CURLE_OPERATION_TIMEOUTED 7.1 7.17.0
@@ -270,10 +270,10 @@ CURLKHTYPE_RSA1 7.19.6
CURLKHTYPE_UNKNOWN 7.19.6
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0
CURLMOPT_MAXCONNECTS 7.16.3
CURLMOPT_MAX_HOST_CONNECTIONS 7.30.0
CURLMOPT_MAX_PIPELINE_LENGTH 7.30.0
CURLMOPT_MAX_TOTAL_CONNECTIONS 7.30.0
CURLMOPT_MAXCONNECTS 7.16.3
CURLMOPT_PIPELINING 7.16.0
CURLMOPT_PIPELINING_SERVER_BL 7.30.0
CURLMOPT_PIPELINING_SITE_BL 7.30.0
@@ -283,6 +283,7 @@ CURLMOPT_TIMERDATA 7.16.0
CURLMOPT_TIMERFUNCTION 7.16.0
CURLMSG_DONE 7.9.6
CURLMSG_NONE 7.9.6
CURLM_ADDED_ALREADY 7.32.1
CURLM_BAD_EASY_HANDLE 7.9.6
CURLM_BAD_HANDLE 7.9.6
CURLM_BAD_SOCKET 7.15.4
@@ -331,6 +332,9 @@ CURLOPT_DEBUGDATA 7.9.6
CURLOPT_DEBUGFUNCTION 7.9.6
CURLOPT_DIRLISTONLY 7.17.0
CURLOPT_DNS_CACHE_TIMEOUT 7.9.3
CURLOPT_DNS_INTERFACE 7.33.0
CURLOPT_DNS_LOCAL_IP4 7.33.0
CURLOPT_DNS_LOCAL_IP6 7.33.0
CURLOPT_DNS_SERVERS 7.24.0
CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1
CURLOPT_EGDSOCKET 7.7
@@ -527,6 +531,7 @@ CURLOPT_WRITEHEADER 7.1
CURLOPT_WRITEINFO 7.1
CURLOPT_XFERINFODATA 7.32.0
CURLOPT_XFERINFOFUNCTION 7.32.0
CURLOPT_XOAUTH2_BEARER 7.33.0
CURLPAUSE_ALL 7.18.0
CURLPAUSE_CONT 7.18.0
CURLPAUSE_RECV 7.18.0
@@ -620,14 +625,15 @@ CURL_FORMADD_NULL 7.9.8
CURL_FORMADD_OK 7.9.8
CURL_FORMADD_OPTION_TWICE 7.9.8
CURL_FORMADD_UNKNOWN_OPTION 7.9.8
CURL_GLOBAL_ACK_EINTR 7.30.0
CURL_GLOBAL_ALL 7.8
CURL_GLOBAL_DEFAULT 7.8
CURL_GLOBAL_NOTHING 7.8
CURL_GLOBAL_SSL 7.8
CURL_GLOBAL_WIN32 7.8.1
CURL_GLOBAL_ACK_EINTR 7.30.0
CURL_HTTP_VERSION_1_0 7.9.1
CURL_HTTP_VERSION_1_1 7.9.1
CURL_HTTP_VERSION_2_0 7.33.0
CURL_HTTP_VERSION_NONE 7.9.1
CURL_IPRESOLVE_V4 7.10.8
CURL_IPRESOLVE_V6 7.10.8
@@ -700,6 +706,7 @@ CURL_VERSION_CONV 7.15.4
CURL_VERSION_CURLDEBUG 7.19.6
CURL_VERSION_DEBUG 7.10.6
CURL_VERSION_GSSNEGOTIATE 7.10.6
CURL_VERSION_HTTP2 7.33.0
CURL_VERSION_IDN 7.12.0
CURL_VERSION_IPV6 7.10
CURL_VERSION_KERBEROS4 7.10

View File

@@ -645,16 +645,18 @@ typedef enum {
#define CURL_ERROR_SIZE 256
struct curl_khkey {
const char *key; /* points to a zero-terminated string encoded with base64
if len is zero, otherwise to the "raw" data */
size_t len;
enum type {
enum curl_khtype {
CURLKHTYPE_UNKNOWN,
CURLKHTYPE_RSA1,
CURLKHTYPE_RSA,
CURLKHTYPE_DSS
} keytype;
};
struct curl_khkey {
const char *key; /* points to a zero-terminated string encoded with base64
if len is zero, otherwise to the "raw" data */
size_t len;
enum curl_khtype keytype;
};
/* this is the set of return values expected from the curl_sshkeycallback
@@ -1551,6 +1553,22 @@ typedef enum {
* prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
/* The XOAUTH2 bearer token */
CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
/* Set the interface string to use as outgoing network
* interface for DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
/* Set the local IPv4 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
/* Set the local IPv4 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1603,6 +1621,7 @@ enum {
for us! */
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
};
@@ -2166,6 +2185,7 @@ typedef struct {
#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
/*
* NAME curl_version_info()

View File

@@ -30,12 +30,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.32.0-DEV"
#define LIBCURL_VERSION "7.33.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 32
#define LIBCURL_VERSION_MINOR 33
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -53,7 +53,7 @@
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x072000
#define LIBCURL_VERSION_NUM 0x072100
/*
* This is the date and time when the full source package was created. The

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -64,6 +64,8 @@ typedef enum {
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
CURLM_LAST
} CURLMcode;

View File

@@ -264,6 +264,11 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
(option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_XOAUTH2_BEARER || \
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DNS_INTERFACE || \
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
0)
/* evaluates to true if option takes a curl_write_callback argument */

View File

@@ -10,7 +10,7 @@
CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
netrc.c getinfo.c transfer.c strequal.c easy.c security.c \
curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c krb5.c \
memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
content_encoding.c share.c http_digest.c md4.c md5.c \
@@ -26,12 +26,12 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_ntlm_msgs.c \
curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c \
hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c \
gskit.c
gskit.c http2.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
if2ip.h speedcheck.h urldata.h curl_ldap.h ssluse.h escape.h telnet.h \
getinfo.h strequal.h krb4.h memdebug.h http_chunks.h \
getinfo.h strequal.h curl_sec.h memdebug.h http_chunks.h \
curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h strtok.h \
connect.h llist.h hash.h content_encoding.h share.h curl_md4.h \
curl_md5.h http_digest.h http_negotiate.h inet_pton.h amigaos.h \
@@ -45,4 +45,5 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
asyn.h curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \
curl_ntlm_msgs.h curl_sasl.h curl_schannel.h curl_multibyte.h \
curl_darwinssl.h hostcheck.h bundles.h conncache.h curl_setup_once.h \
multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h
multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h \
http2.h

View File

@@ -566,7 +566,6 @@ X_OBJS= \
$(DIROBJ)\imap.obj \
$(DIROBJ)\inet_ntop.obj \
$(DIROBJ)\inet_pton.obj \
$(DIROBJ)\krb4.obj \
$(DIROBJ)\krb5.obj \
$(DIROBJ)\ldap.obj \
$(DIROBJ)\llist.obj \

31
lib/README.http2 Normal file
View File

@@ -0,0 +1,31 @@
HTTP2 with libcurl
Spec: http://tools.ietf.org/html/draft-ietf-httpbis-http2-06
nghttp2 (https://github.com/tatsuhiro-t/nghttp2)
We're depending on this 3rd party library for the actual low level protocol
handling parts. The reason for this is that HTTP2 is much more complex at
that layer than HTTP1.1 (which we implement on our own) and that nghttp2 is
an already existing and well functional library.
Over an http:// URL
If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will include
an upgrade header in the initial request to the host to allow upgrading to
http2. Possibly introduce an option that will cause libcurl to fail if not
possible to upgrade. Possibly introduce an option that makes libcurl use
http2 at once over http://
Over an https:// URL
If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will use ALPN
(or NPN) to negotiate which protocol to continue with. Possibly introduce an
option that will cause libcurl to fail if not possible to use http2.
To consider:
- How to tell libcurl when using the multi interface that all or some of the
handles are allowed to re-use the same physical connection. Can we just
re-use existing pipelining logic?

View File

@@ -623,4 +623,72 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
#endif
return result;
}
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
const char *interf)
{
#if (ARES_VERSION >= 0x010704)
if(!interf)
interf = "";
ares_set_local_dev((ares_channel)data->state.resolver, interf);
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
(void)interf;
return CURLE_NOT_BUILT_IN;
#endif
}
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
const char *local_ip4)
{
#if (ARES_VERSION >= 0x010704)
uint32_t a4;
if((!local_ip4) || (local_ip4[0] == 0)) {
a4 = 0; /* disabled: do not bind to a specific address */
}
else {
if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4));
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
(void)local_ip4;
return CURLE_NOT_BUILT_IN;
#endif
}
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
const char *local_ip6)
{
#if (ARES_VERSION >= 0x010704)
unsigned char a6[INET6_ADDRSTRLEN];
if((!local_ip6) || (local_ip6[0] == 0)) {
/* disabled: do not bind to a specific address */
memset(a6, 0, sizeof(a6));
}
else {
if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
ares_set_local_ip6((ares_channel)data->state.resolver, a6);
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
(void)local_ip6;
return CURLE_NOT_BUILT_IN;
#endif
}
#endif /* CURLRES_ARES */

View File

@@ -265,7 +265,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
{
struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
char service [NI_MAXSERV];
char service[12];
int rc;
snprintf(service, sizeof(service), "%d", tsd->port);
@@ -559,7 +559,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
struct in_addr in;
Curl_addrinfo *res;
int error;
char sbuf[NI_MAXSERV];
char sbuf[12];
int pf = PF_INET;
#ifdef CURLRES_IPV6
struct in6_addr in6;
@@ -635,4 +635,28 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
}
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
const char *interf)
{
(void)data;
(void)interf;
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
const char *local_ip4)
{
(void)data;
(void)local_ip4;
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
const char *local_ip6)
{
(void)data;
(void)local_ip6;
return CURLE_NOT_BUILT_IN;
}
#endif /* CURLRES_THREADED */

View File

@@ -390,21 +390,6 @@
# define SIZEOF_SIZE_T 4
#endif
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
/* Define if you have struct sockaddr_storage. */
#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
#endif
/* Define if you have struct timeval. */
#define HAVE_STRUCT_TIMEVAL 1
/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* ---------------------------------------------------------------- */
/* BSD-style lwIP TCP/IP stack SPECIFIC */
/* ---------------------------------------------------------------- */
@@ -572,6 +557,25 @@
# endif
#endif
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
/* Define if you have struct sockaddr_storage. */
#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
#endif
/* Define if you have struct timeval. */
#define HAVE_STRUCT_TIMEVAL 1
/* Define if struct sockaddr_in6 has the sin6_scope_id member. */
#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
#if HAVE_WINSOCK2_H && defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
#define HAVE_STRUCT_POLLFD 1
#endif
/* ---------------------------------------------------------------- */
/* LARGE FILE SUPPORT */
/* ---------------------------------------------------------------- */

View File

@@ -290,6 +290,34 @@ static void strstore(char **str, const char *newstr)
*str = strdup(newstr);
}
/*
* remove_expired() removes expired cookies.
*/
static void remove_expired(struct CookieInfo *cookies)
{
struct Cookie *co, *nx, *pv;
curl_off_t now = (curl_off_t)time(NULL);
co = cookies->cookies;
pv = NULL;
while(co) {
nx = co->next;
if((co->expirestr || co->maxage) && co->expires < now) {
if(co == cookies->cookies) {
cookies->cookies = co->next;
}
else {
pv->next = co->next;
}
cookies->numcookies--;
freecookie(co);
}
else {
pv = co;
}
co = nx;
}
}
/****************************************************************************
*
@@ -700,6 +728,9 @@ Curl_cookie_add(struct SessionHandle *data,
superceeds an already existing cookie, which it may if the previous have
the same domain and path as this */
/* at first, remove expired cookies */
remove_expired(c);
clist = c->cookies;
replace_old = FALSE;
while(clist) {
@@ -931,6 +962,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
if(!c || !c->cookies)
return NULL; /* no cookie struct or no cookies in the struct */
/* at first, remove expired cookies */
remove_expired(c);
co = c->cookies;
while(co) {
@@ -1173,6 +1207,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
destination file */
return 0;
/* at first, remove expired cookies */
remove_expired(c);
if(strequal("-", dumphere)) {
/* use stdout */
out = stdout;

View File

@@ -52,12 +52,14 @@
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
#define CURL_BUILD_IOS 0
#define CURL_BUILD_IOS_7 0
#define CURL_BUILD_MAC 1
/* This is the maximum API level we are allowed to use when building: */
#define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
#define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
#define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
#define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
/* These macros mean "the following code is present to allow runtime backward
compatibility with at least this cat or earlier":
(You set this at build-time by setting the MACOSX_DEPLOYMENT_TARGET
@@ -66,9 +68,11 @@
#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
#define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
#define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
#elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
#define CURL_BUILD_IOS 1
#define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
#define CURL_BUILD_MAC 0
#define CURL_BUILD_MAC_10_5 0
#define CURL_BUILD_MAC_10_6 0
@@ -660,6 +664,110 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
break;
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
/* TLS PSK (RFC 4279): */
case TLS_PSK_WITH_RC4_128_SHA:
return "TLS_PSK_WITH_RC4_128_SHA";
break;
case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
break;
case TLS_PSK_WITH_AES_128_CBC_SHA:
return "TLS_PSK_WITH_AES_128_CBC_SHA";
break;
case TLS_PSK_WITH_AES_256_CBC_SHA:
return "TLS_PSK_WITH_AES_256_CBC_SHA";
break;
case TLS_DHE_PSK_WITH_RC4_128_SHA:
return "TLS_DHE_PSK_WITH_RC4_128_SHA";
break;
case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
break;
case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
break;
case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
break;
case TLS_RSA_PSK_WITH_RC4_128_SHA:
return "TLS_RSA_PSK_WITH_RC4_128_SHA";
break;
case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
break;
case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
break;
case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
break;
/* More TLS PSK (RFC 4785): */
case TLS_PSK_WITH_NULL_SHA:
return "TLS_PSK_WITH_NULL_SHA";
break;
case TLS_DHE_PSK_WITH_NULL_SHA:
return "TLS_DHE_PSK_WITH_NULL_SHA";
break;
case TLS_RSA_PSK_WITH_NULL_SHA:
return "TLS_RSA_PSK_WITH_NULL_SHA";
break;
/* Even more TLS PSK (RFC 5487): */
case TLS_PSK_WITH_AES_128_GCM_SHA256:
return "TLS_PSK_WITH_AES_128_GCM_SHA256";
break;
case TLS_PSK_WITH_AES_256_GCM_SHA384:
return "TLS_PSK_WITH_AES_256_GCM_SHA384";
break;
case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
break;
case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
break;
case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
break;
case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
return "TLS_PSK_WITH_AES_256_GCM_SHA384";
break;
case TLS_PSK_WITH_AES_128_CBC_SHA256:
return "TLS_PSK_WITH_AES_128_CBC_SHA256";
break;
case TLS_PSK_WITH_AES_256_CBC_SHA384:
return "TLS_PSK_WITH_AES_256_CBC_SHA384";
break;
case TLS_PSK_WITH_NULL_SHA256:
return "TLS_PSK_WITH_NULL_SHA256";
break;
case TLS_PSK_WITH_NULL_SHA384:
return "TLS_PSK_WITH_NULL_SHA384";
break;
case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
break;
case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
break;
case TLS_DHE_PSK_WITH_NULL_SHA256:
return "TLS_DHE_PSK_WITH_NULL_SHA256";
break;
case TLS_DHE_PSK_WITH_NULL_SHA384:
return "TLS_RSA_PSK_WITH_NULL_SHA384";
break;
case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
break;
case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
break;
case TLS_RSA_PSK_WITH_NULL_SHA256:
return "TLS_RSA_PSK_WITH_NULL_SHA256";
break;
case TLS_RSA_PSK_WITH_NULL_SHA384:
return "TLS_RSA_PSK_WITH_NULL_SHA384";
break;
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
}
return "TLS_NULL_WITH_NULL_NULL";
}
@@ -819,6 +927,68 @@ static OSStatus CopyIdentityWithLabel(char *label,
return status;
}
static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
const char *cPassword,
SecIdentityRef *out_cert_and_key)
{
OSStatus status = errSecItemNotFound;
CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
(const UInt8 *)cPath, strlen(cPath), false);
CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
cPassword, kCFStringEncodingUTF8) : NULL;
CFDataRef pkcs_data = NULL;
/* We can import P12 files on iOS or OS X 10.6 or later: */
#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
NULL, NULL, &status)) {
const void *cKeys[] = {kSecImportExportPassphrase};
const void *cValues[] = {password};
CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
password ? 1L : 0L, NULL, NULL);
CFArrayRef items = NULL;
/* Here we go: */
status = SecPKCS12Import(pkcs_data, options, &items);
if(status == noErr) {
CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
kSecImportItemIdentity);
/* Retain the identity; we don't care about any other data... */
CFRetain(temp_identity);
*out_cert_and_key = (SecIdentityRef)temp_identity;
CFRelease(items);
}
CFRelease(options);
CFRelease(pkcs_data);
}
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
if(password)
CFRelease(password);
CFRelease(pkcs_url);
return status;
}
/* This code was borrowed from nss.c, with some modifications:
* Determine whether the nickname passed in is a filename that needs to
* be loaded as a PEM or a regular NSS nickname.
*
* returns 1 for a file
* returns 0 for not a file
*/
CF_INLINE bool is_file(const char *filename)
{
struct_stat st;
if(filename == NULL)
return false;
if(stat(filename, &st) == 0)
return S_ISREG(st.st_mode);
return false;
}
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
int sockindex)
{
@@ -988,9 +1158,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
if(data->set.str[STRING_CERT]) {
SecIdentityRef cert_and_key = NULL;
bool is_cert_file = is_file(data->set.str[STRING_CERT]);
/* User wants to authenticate with a client cert. Look for it: */
/* User wants to authenticate with a client cert. Look for it:
If we detect that this is a file on disk, then let's load it.
Otherwise, assume that the user wants to use an identity loaded
from the Keychain. */
if(is_cert_file) {
if(!data->set.str[STRING_CERT_TYPE])
infof(data, "WARNING: SSL: Certificate type not set, assuming "
"PKCS#12 format.\n");
else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
strlen(data->set.str[STRING_CERT_TYPE])) != 0)
infof(data, "WARNING: SSL: The Security framework only supports "
"loading identities that are in PKCS#12 format.\n");
err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
data->set.str[STRING_KEY_PASSWD], &cert_and_key);
}
else
err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
if(err == noErr) {
SecCertificateRef cert = NULL;
CFTypeRef certs_c[1];
@@ -1027,8 +1215,29 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
CFRelease(cert_and_key);
}
else {
failf(data, "SSL: Can't find the certificate \"%s\" and its private key "
"in the Keychain.", data->set.str[STRING_CERT]);
switch(err) {
case errSecPkcs12VerifyFailure: case errSecAuthFailed:
failf(data, "SSL: Incorrect password for the certificate \"%s\" "
"and its private key.", data->set.str[STRING_CERT]);
break;
case errSecDecode: case errSecUnknownFormat:
failf(data, "SSL: Couldn't make sense of the data in the "
"certificate \"%s\" and its private key.",
data->set.str[STRING_CERT]);
break;
case errSecPassphraseRequired:
failf(data, "SSL The certificate \"%s\" requires a password.",
data->set.str[STRING_CERT]);
break;
case errSecItemNotFound:
failf(data, "SSL: Can't find the certificate \"%s\" and its private "
"key in the Keychain.", data->set.str[STRING_CERT]);
break;
default:
failf(data, "SSL: Can't load the certificate \"%s\" and its private "
"key: OSStatus %d", data->set.str[STRING_CERT], err);
break;
}
return CURLE_SSL_CERTPROBLEM;
}
}
@@ -1121,11 +1330,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
case SSL_NULL_WITH_NULL_NULL:
case SSL_RSA_WITH_NULL_MD5:
case SSL_RSA_WITH_NULL_SHA:
case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
/* Disable anonymous ciphersuites: */
case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
case SSL_DH_anon_WITH_RC4_128_MD5:
@@ -1181,6 +1400,13 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
Curl_safefree(all_ciphers);
Curl_safefree(allowed_ciphers);
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
/* We want to enable 1/n-1 when using a CBC cipher unless the user
specifically doesn't want us doing that: */
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
!data->set.ssl_enable_beast);
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
/* Check if there's a cached ID we can/should use here! */
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
&ssl_sessionid_len)) {

View File

@@ -22,6 +22,7 @@
* RFC2831 DIGEST-MD5 authentication
* RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication
* RFC6749 OAuth 2.0 Authorization Framework
*
***************************************************************************/
@@ -94,18 +95,18 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
const char *passwdp,
char **outptr, size_t *outlen)
{
char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH];
CURLcode result;
char *plainauth;
size_t ulen;
size_t plen;
ulen = strlen(userp);
plen = strlen(passwdp);
if(2 * ulen + plen + 2 > sizeof(plainauth)) {
plainauth = malloc(2 * ulen + plen + 2);
if(!plainauth) {
*outlen = 0;
*outptr = NULL;
/* Plainauth too small */
return CURLE_OUT_OF_MEMORY;
}
@@ -117,8 +118,10 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
/* Base64 encode the reply */
return Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
outlen);
Curl_safefree(plainauth);
return result;
}
/*
@@ -190,7 +193,7 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
size_t chlglen = 0;
HMAC_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char response[MAX_CURL_USER_LENGTH + 2 * MD5_DIGEST_LEN + 1];
char *response;
/* Decode the challenge if necessary */
if(chlg64len && *chlg64 != '=') {
@@ -220,14 +223,19 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
Curl_HMAC_final(ctxt, digest);
/* Prepare the response */
snprintf(response, sizeof(response),
response = aprintf(
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
userp, digest[0], digest[1], digest[2], digest[3], digest[4],
digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
digest[11], digest[12], digest[13], digest[14], digest[15]);
if(!response)
return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */
return Curl_base64_encode(data, response, 0, outptr, outlen);
result = Curl_base64_encode(data, response, 0, outptr, outlen);
Curl_safefree(response);
return result;
}
/*
@@ -470,6 +478,40 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
}
#endif /* USE_NTLM */
/*
* Curl_sasl_create_xoauth2_message()
*
* This is used to generate an already encoded XOAUTH2 message ready
* for sending to the recipient.
*
* Parameters:
*
* data [in] - The session handle.
* user [in] - The user name.
* bearer [in] - The XOAUTH Bearer token.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
const char *user,
const char *bearer,
char **outptr, size_t *outlen)
{
char *xoauth;
xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
if(!xoauth)
return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */
return Curl_base64_encode(data, xoauth, strlen(xoauth), outptr,
outlen);
}
/*
* Curl_sasl_cleanup()
*

View File

@@ -24,6 +24,10 @@
#include "pingpong.h"
/* Authentication mechanism values */
#define SASL_AUTH_NONE 0
#define SASL_AUTH_ANY ~0U
/* Authentication mechanism flags */
#define SASL_MECH_LOGIN (1 << 0)
#define SASL_MECH_PLAIN (1 << 1)
@@ -32,10 +36,22 @@
#define SASL_MECH_GSSAPI (1 << 4)
#define SASL_MECH_EXTERNAL (1 << 5)
#define SASL_MECH_NTLM (1 << 6)
#define SASL_MECH_XOAUTH2 (1 << 7)
/* Authentication mechanism values */
#define SASL_AUTH_NONE 0
#define SASL_AUTH_ANY ~0
/* Authentication mechanism strings */
#define SASL_MECH_STRING_LOGIN "LOGIN"
#define SASL_MECH_STRING_PLAIN "PLAIN"
#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
#define SASL_MECH_STRING_GSSAPI "GSSAPI"
#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
#define SASL_MECH_STRING_NTLM "NTLM"
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
/* This is used to test whether the line starts with the given mechanism */
#define sasl_mech_equal(line, wordlen, mech) \
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
!memcmp(line, mech, wordlen))
/* This is used to generate a base64 encoded PLAIN authentication message */
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
@@ -85,6 +101,13 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
#endif /* USE_NTLM */
/* This is used to generate a base64 encoded XOAUTH2 authentication message
containing the user name and bearer token */
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
const char *user,
const char *bearer,
char **outptr, size_t *outlen);
/* This is used to cleanup any libraries or curl modules used by the sasl
functions */
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);

View File

@@ -1,5 +1,5 @@
#ifndef HEADER_CURL_KRB4_H
#define HEADER_CURL_KRB4_H
#ifndef HEADER_CURL_SECURITY_H
#define HEADER_CURL_SECURITY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,24 +34,18 @@ struct Curl_sec_client_mech {
int (*decode)(void *, void*, int, int, struct connectdata *);
};
#define AUTH_OK 0
#define AUTH_CONTINUE 1
#define AUTH_ERROR 2
#ifdef HAVE_KRB4
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
#endif
#ifdef HAVE_GSSAPI
extern struct Curl_sec_client_mech Curl_krb5_client_mech;
#endif
CURLcode Curl_krb_kauth(struct connectdata *conn);
int Curl_sec_read_msg (struct connectdata *conn, char *,
enum protection_level);
void Curl_sec_end (struct connectdata *);
CURLcode Curl_sec_login (struct connectdata *);
int Curl_sec_request_prot (struct connectdata *conn, const char *level);
#endif /* HEADER_CURL_KRB4_H */
extern struct Curl_sec_client_mech Curl_krb5_client_mech;
#endif
#endif /* HEADER_CURL_SECURITY_H */

View File

@@ -440,7 +440,7 @@ typedef int sig_atomic_t;
* (or equivalent) on this platform to hide platform details to code using it.
*/
#ifdef WIN32
#if defined(WIN32) && !defined(USE_LWIPSOCK)
#define ERRNO ((int)GetLastError())
#define SET_ERRNO(x) (SetLastError((DWORD)(x)))
#else

View File

@@ -453,70 +453,275 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
return ret;
}
/*
* curl_easy_perform() is the external interface that performs a blocking
* transfer as previously setup.
#ifdef CURLDEBUG
struct socketmonitor {
struct socketmonitor *next; /* the next node in the list or NULL */
struct pollfd socket; /* socket info of what to monitor */
};
struct events {
long ms; /* timeout, run the timeout function when reached */
bool msbump; /* set TRUE when timeout is set by callback */
int num_sockets; /* number of nodes in the monitor list */
struct socketmonitor *list; /* list of sockets to monitor */
int running_handles; /* store the returned number */
};
/* events_timer
*
* CONCEPT: This function creates a multi handle, adds the easy handle to it,
* runs curl_multi_perform() until the transfer is done, then detaches the
* easy handle, destroys the multi handle and returns the easy handle's return
* code.
*
* REALITY: it can't just create and destroy the multi handle that easily. It
* needs to keep it around since if this easy handle is used again by this
* function, the same multi handle must be re-used so that the same pools and
* caches can be used.
* Callback that gets called with a new value when the timeout should be
* updated.
*/
CURLcode curl_easy_perform(CURL *easy)
static int events_timer(CURLM *multi, /* multi handle */
long timeout_ms, /* see above */
void *userp) /* private callback pointer */
{
struct events *ev = userp;
(void)multi;
if(timeout_ms == -1)
/* timeout removed */
timeout_ms = 0;
else if(timeout_ms == 0)
/* timeout is already reached! */
timeout_ms = 1; /* trigger asap */
ev->ms = timeout_ms;
ev->msbump = TRUE;
return 0;
}
/* poll2cselect
*
* convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
*/
static int poll2cselect(int pollmask)
{
int omask=0;
if(pollmask & POLLIN)
omask |= CURL_CSELECT_IN;
if(pollmask & POLLOUT)
omask |= CURL_CSELECT_OUT;
if(pollmask & POLLERR)
omask |= CURL_CSELECT_ERR;
return omask;
}
/* socketcb2poll
*
* convert from libcurl' CURL_POLL_* bit definitions to poll()'s
*/
static short socketcb2poll(int pollmask)
{
short omask=0;
if(pollmask & CURL_POLL_IN)
omask |= POLLIN;
if(pollmask & CURL_POLL_OUT)
omask |= POLLOUT;
return omask;
}
/* events_socket
*
* Callback that gets called with information about socket activity to
* monitor.
*/
static int events_socket(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
void *userp, /* private callback
pointer */
void *socketp) /* private socket
pointer */
{
struct events *ev = userp;
struct socketmonitor *m;
struct socketmonitor *prev=NULL;
(void)socketp;
m = ev->list;
while(m) {
if(m->socket.fd == s) {
if(what == CURL_POLL_REMOVE) {
struct socketmonitor *nxt = m->next;
/* remove this node from the list of monitored sockets */
if(prev)
prev->next = nxt;
else
ev->list = nxt;
free(m);
m = nxt;
infof(easy, "socket cb: socket %d REMOVED\n", s);
}
else {
/* The socket 's' is already being monitored, update the activity
mask. Convert from libcurl bitmask to the poll one. */
m->socket.events = socketcb2poll(what);
infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
what&CURL_POLL_IN?"IN":"",
what&CURL_POLL_OUT?"OUT":"");
}
break;
}
prev = m;
m = m->next; /* move to next node */
}
if(!m) {
if(what == CURL_POLL_REMOVE) {
/* this happens a bit too often, libcurl fix perhaps? */
/* fprintf(stderr,
"%s: socket %d asked to be REMOVED but not present!\n",
__func__, s); */
}
else {
m = malloc(sizeof(struct socketmonitor));
m->next = ev->list;
m->socket.fd = s;
m->socket.events = socketcb2poll(what);
m->socket.revents = 0;
ev->list = m;
infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
what&CURL_POLL_IN?"IN":"",
what&CURL_POLL_OUT?"OUT":"");
}
}
return 0;
}
/*
* events_setup()
*
* Do the multi handle setups that only event-based transfers need.
*/
static void events_setup(CURLM *multi, struct events *ev)
{
/* timer callback */
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
/* socket callback */
curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
}
/* wait_or_timeout()
*
* waits for activity on any of the given sockets, or the timeout to trigger.
*/
static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
{
CURLM *multi;
CURLMcode mcode;
CURLcode code = CURLE_OK;
CURLMsg *msg;
bool done = FALSE;
int rc;
struct SessionHandle *data = easy;
CURLMcode mcode;
CURLcode rc = CURLE_OK;
while(!done) {
CURLMsg *msg;
struct socketmonitor *m;
struct pollfd *f;
struct pollfd fds[4];
int numfds=0;
int pollrc;
int i;
struct timeval before;
struct timeval after;
/* populate the fds[] array */
for(m = ev->list, f=&fds[0]; m; m = m->next) {
f->fd = m->socket.fd;
f->events = m->socket.events;
f->revents = 0;
/* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
f++;
numfds++;
}
/* get the time stamp to use to figure out how long poll takes */
before = curlx_tvnow();
/* wait for activity or timeout */
pollrc = Curl_poll(fds, numfds, (int)ev->ms);
after = curlx_tvnow();
ev->msbump = FALSE; /* reset here */
if(0 == pollrc) {
/* timeout! */
ev->ms = 0;
/* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */
mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
&ev->running_handles);
}
else if(pollrc > 0) {
/* loop over the monitored sockets to see which ones had activity */
for(i = 0; i< numfds; i++) {
if(fds[i].revents) {
/* socket activity, tell libcurl */
int act = poll2cselect(fds[i].revents); /* convert */
infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n",
fds[i].fd);
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
&ev->running_handles);
}
}
if(!ev->msbump)
/* If nothing updated the timeout, we decrease it by the spent time.
* If it was updated, it has the new timeout time stored already.
*/
ev->ms += curlx_tvdiff(after, before);
}
if(mcode)
return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
/* we don't really care about the "msgs_in_queue" value returned in the
second argument */
msg = curl_multi_info_read(multi, &pollrc);
if(msg) {
rc = msg->data.result;
done = TRUE;
}
}
return rc;
}
/* easy_events()
*
* Runs a transfer in a blocking manner using the events-based API
*/
static CURLcode easy_events(CURLM *multi)
{
struct events evs= {2, FALSE, 0, NULL, 0};
/* if running event-based, do some further multi inits */
events_setup(multi, &evs);
return wait_or_timeout(multi, &evs);
}
#else /* CURLDEBUG */
/* when not built with debug, this function doesn't exist */
#define easy_events(x) CURLE_NOT_BUILT_IN
#endif
static CURLcode easy_transfer(CURLM *multi)
{
bool done = FALSE;
CURLMcode mcode = CURLM_OK;
CURLcode code = CURLE_OK;
struct timeval before;
int without_fds = 0; /* count number of consecutive returns from
curl_multi_wait() without any filedescriptors */
struct timeval before;
SIGPIPE_VARIABLE(pipe_st);
if(!easy)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(data->multi) {
failf(data, "easy handled already used in multi handle");
return CURLE_FAILED_INIT;
}
if(data->multi_easy)
multi = data->multi_easy;
else {
/* this multi handle will only ever have a single easy handled attached
to it, so make it use minimal hashes */
multi = Curl_multi_handle(1, 3);
if(!multi)
return CURLE_OUT_OF_MEMORY;
data->multi_easy = multi;
}
/* Copy the MAXCONNECTS option to the multi handle */
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
mcode = curl_multi_add_handle(multi, easy);
if(mcode) {
curl_multi_cleanup(multi);
if(mcode == CURLM_OUT_OF_MEMORY)
return CURLE_OUT_OF_MEMORY;
else
return CURLE_FAILED_INIT;
}
sigpipe_ignore(data, &pipe_st);
/* assign this after curl_multi_add_handle() since that function checks for
it and rejects this handle otherwise */
data->multi = multi;
while(!done && !mcode) {
int still_running;
@@ -556,17 +761,85 @@ CURLcode curl_easy_perform(CURL *easy)
/* only read 'still_running' if curl_multi_perform() return OK */
if((mcode == CURLM_OK) && !still_running) {
msg = curl_multi_info_read(multi, &rc);
int rc;
CURLMsg *msg = curl_multi_info_read(multi, &rc);
if(msg) {
code = msg->data.result;
done = TRUE;
}
}
}
return code;
}
/*
* easy_perform() is the external interface that performs a blocking
* transfer as previously setup.
*
* CONCEPT: This function creates a multi handle, adds the easy handle to it,
* runs curl_multi_perform() until the transfer is done, then detaches the
* easy handle, destroys the multi handle and returns the easy handle's return
* code.
*
* REALITY: it can't just create and destroy the multi handle that easily. It
* needs to keep it around since if this easy handle is used again by this
* function, the same multi handle must be re-used so that the same pools and
* caches can be used.
*
* DEBUG: if 'events' is set TRUE, this function will use a replacement engine
* instead of curl_multi_perform() and use curl_multi_socket_action().
*/
static CURLcode easy_perform(struct SessionHandle *data, bool events)
{
CURLM *multi;
CURLMcode mcode;
CURLcode code = CURLE_OK;
SIGPIPE_VARIABLE(pipe_st);
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(data->multi) {
failf(data, "easy handled already used in multi handle");
return CURLE_FAILED_INIT;
}
if(data->multi_easy)
multi = data->multi_easy;
else {
/* this multi handle will only ever have a single easy handled attached
to it, so make it use minimal hashes */
multi = Curl_multi_handle(1, 3);
if(!multi)
return CURLE_OUT_OF_MEMORY;
data->multi_easy = multi;
}
/* Copy the MAXCONNECTS option to the multi handle */
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
mcode = curl_multi_add_handle(multi, data);
if(mcode) {
curl_multi_cleanup(multi);
if(mcode == CURLM_OUT_OF_MEMORY)
return CURLE_OUT_OF_MEMORY;
else
return CURLE_FAILED_INIT;
}
sigpipe_ignore(data, &pipe_st);
/* assign this after curl_multi_add_handle() since that function checks for
it and rejects this handle otherwise */
data->multi = multi;
/* run the transfer */
code = events ? easy_events(multi) : easy_transfer(multi);
/* ignoring the return code isn't nice, but atm we can't really handle
a failure here, room for future improvement! */
(void)curl_multi_remove_handle(multi, easy);
(void)curl_multi_remove_handle(multi, data);
sigpipe_restore(&pipe_st);
@@ -574,6 +847,28 @@ CURLcode curl_easy_perform(CURL *easy)
return code;
}
/*
* curl_easy_perform() is the external interface that performs a blocking
* transfer as previously setup.
*/
CURLcode curl_easy_perform(CURL *easy)
{
return easy_perform(easy, FALSE);
}
#ifdef CURLDEBUG
/*
* curl_easy_perform_ev() is the external interface that performs a blocking
* transfer using the event-based API internally.
*/
CURLcode curl_easy_perform_ev(CURL *easy)
{
return easy_perform(easy, TRUE);
}
#endif
/*
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
* easy handle.
@@ -591,22 +886,6 @@ void curl_easy_cleanup(CURL *curl)
sigpipe_restore(&pipe_st);
}
/*
* Store a pointed to the multi handle within the easy handle's data struct.
*/
void Curl_easy_addmulti(struct SessionHandle *data,
void *multi)
{
data->multi = multi;
}
void Curl_easy_initHandleData(struct SessionHandle *data)
{
memset(&data->req, 0, sizeof(struct SingleRequest));
data->req.maxdownload = -1;
}
/*
* curl_easy_getinfo() is an external interface that allows an app to retrieve
* information from a performed transfer and similar.
@@ -703,8 +982,6 @@ CURL *curl_easy_duphandle(CURL *incurl)
Curl_convert_setup(outcurl);
Curl_easy_initHandleData(outcurl);
outcurl->magic = CURLEASY_MAGIC_NUMBER;
/* we reach this point and thus we are OK */
@@ -738,7 +1015,7 @@ void curl_easy_reset(CURL *curl)
data->state.path = NULL;
Curl_safefree(data->state.proto.generic);
Curl_free_request_state(data);
/* zero out UserDefined data: */
Curl_freeset(data);
@@ -748,9 +1025,6 @@ void curl_easy_reset(CURL *curl)
/* zero out Progress data: */
memset(&data->progress, 0, sizeof(struct Progress));
/* init Handle data */
Curl_easy_initHandleData(data);
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
}

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,9 +25,9 @@
/*
* Prototypes for library-wide functions provided by easy.c
*/
void Curl_easy_addmulti(struct SessionHandle *data, void *multi);
void Curl_easy_initHandleData(struct SessionHandle *data);
#ifdef CURLDEBUG
CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
#endif
#endif /* HEADER_CURL_EASYIF_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -90,7 +90,7 @@ static CURLcode file_done(struct connectdata *conn,
static CURLcode file_connect(struct connectdata *conn, bool *done);
static CURLcode file_disconnect(struct connectdata *conn,
bool dead_connection);
static CURLcode file_setup_connection(struct connectdata *conn);
/*
* FILE scheme handler.
@@ -98,7 +98,7 @@ static CURLcode file_disconnect(struct connectdata *conn,
const struct Curl_handler Curl_handler_file = {
"FILE", /* scheme */
ZERO_NULL, /* setup_connection */
file_setup_connection, /* setup_connection */
file_do, /* do_it */
file_done, /* done */
ZERO_NULL, /* do_more */
@@ -117,6 +117,16 @@ const struct Curl_handler Curl_handler_file = {
};
static CURLcode file_setup_connection(struct connectdata *conn)
{
/* allocate the FILE specific struct */
conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
if(!conn->data->req.protop)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
/*
Check if this is a range download, and if so, set the internal variables
properly. This code is copied from the FTP implementation and might as
@@ -179,39 +189,17 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
{
struct SessionHandle *data = conn->data;
char *real_path;
struct FILEPROTO *file;
struct FILEPROTO *file = data->req.protop;
int fd;
#ifdef DOS_FILESYSTEM
int i;
char *actual_path;
#endif
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
if(!real_path)
return CURLE_OUT_OF_MEMORY;
if(!data->state.proto.file) {
file = calloc(1, sizeof(struct FILEPROTO));
if(!file) {
free(real_path);
return CURLE_OUT_OF_MEMORY;
}
data->state.proto.file = file;
}
else {
/* file is not a protocol that can deal with "persistancy" */
file = data->state.proto.file;
Curl_safefree(file->freepath);
file->path = NULL;
if(file->fd != -1)
close(file->fd);
file->fd = -1;
}
#ifdef DOS_FILESYSTEM
/* If the first character is a slash, and there's
something that looks like a drive at the beginning of
@@ -262,7 +250,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
static CURLcode file_done(struct connectdata *conn,
CURLcode status, bool premature)
{
struct FILEPROTO *file = conn->data->state.proto.file;
struct FILEPROTO *file = conn->data->req.protop;
(void)status; /* not used */
(void)premature; /* not used */
@@ -280,7 +268,7 @@ static CURLcode file_done(struct connectdata *conn,
static CURLcode file_disconnect(struct connectdata *conn,
bool dead_connection)
{
struct FILEPROTO *file = conn->data->state.proto.file;
struct FILEPROTO *file = conn->data->req.protop;
(void)dead_connection; /* not used */
if(file) {
@@ -302,7 +290,7 @@ static CURLcode file_disconnect(struct connectdata *conn,
static CURLcode file_upload(struct connectdata *conn)
{
struct FILEPROTO *file = conn->data->state.proto.file;
struct FILEPROTO *file = conn->data->req.protop;
const char *dir = strchr(file->path, DIRSEP);
int fd;
int mode;
@@ -440,6 +428,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
curl_off_t bytecount = 0;
int fd;
struct timeval now = Curl_tvnow();
struct FILEPROTO *file;
*done = TRUE; /* unconditionally */
@@ -449,8 +438,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
if(data->set.upload)
return file_upload(conn);
file = conn->data->req.protop;
/* get the fd from the connection phase */
fd = conn->data->state.proto.file->fd;
fd = file->fd;
/* VMS: This only works reliable for STREAMLF files */
if(-1 != fstat(fd, &statbuf)) {

237
lib/ftp.c
View File

@@ -59,11 +59,7 @@
#include "ftp.h"
#include "fileinfo.h"
#include "ftplistparser.h"
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#include "krb4.h"
#endif
#include "curl_sec.h"
#include "strtoofft.h"
#include "strequal.h"
#include "sslgen.h"
@@ -225,7 +221,7 @@ const struct Curl_handler Curl_handler_ftps = {
static const struct Curl_handler Curl_handler_ftp_proxy = {
"FTP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -251,7 +247,7 @@ static const struct Curl_handler Curl_handler_ftp_proxy = {
static const struct Curl_handler Curl_handler_ftps_proxy = {
"FTPS", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -493,7 +489,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
static CURLcode InitiateTransfer(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
CURLcode result = CURLE_OK;
if(conn->ssl[SECONDARYSOCKET].use) {
@@ -615,7 +611,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
{
struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
char * const buf = data->state.buffer;
#endif
CURLcode result = CURLE_OK;
@@ -623,7 +619,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
result = Curl_pp_readresp(sockfd, pp, &code, size);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#if defined(HAVE_GSSAPI)
/* handle the security-oriented responses 6xx ***/
/* FIXME: some errorchecking perhaps... ***/
switch(code) {
@@ -775,17 +771,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
return result;
}
/* This is the ONLY way to change FTP state! */
static void _state(struct connectdata *conn,
ftpstate newstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
static const char * const ftp_state_names[]={
"STOP",
"WAIT220",
"AUTH",
@@ -823,11 +811,21 @@ static void _state(struct connectdata *conn,
"QUIT"
};
#endif
/* This is the ONLY way to change FTP state! */
static void _state(struct connectdata *conn,
ftpstate newstate
#ifdef DEBUGBUILD
, int lineno
#endif
)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(ftpc->state != newstate)
infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
(void *)ftpc, lineno, names[ftpc->state], names[newstate]);
(void *)ftpc, lineno, ftp_state_names[ftpc->state],
ftp_state_names[newstate]);
#endif
ftpc->state = newstate;
}
@@ -835,7 +833,7 @@ static void _state(struct connectdata *conn,
static CURLcode ftp_state_user(struct connectdata *conn)
{
CURLcode result;
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
/* send USER */
PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
@@ -874,33 +872,23 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
return GETSOCK_BLANK;
/* When in DO_MORE state, we could be either waiting for us to connect to a
remote site, or we could wait for that site to connect to us. Or just
handle ordinary commands.
When waiting for a connect, we can be in FTP_STOP state (or we're in
FTP_STOR when we do an upload) and then we wait for the secondary socket
to become writeable. . If we're in another state, we're still handling
commands on the control (primary) connection.
* remote site, or we could wait for that site to connect to us. Or just
* handle ordinary commands.
*/
switch(ftpc->state) {
case FTP_STOP:
case FTP_STOR:
break;
default:
if(FTP_STOP == ftpc->state) {
/* if stopped and still in this state, then we're also waiting for a
connect on the secondary connection */
socks[0] = conn->sock[FIRSTSOCKET];
socks[1] = conn->sock[SECONDARYSOCKET];
return GETSOCK_READSOCK(FIRSTSOCKET) |
GETSOCK_WRITESOCK(SECONDARYSOCKET);
}
else
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
}
socks[0] = conn->sock[SECONDARYSOCKET];
if(ftpc->wait_data_conn) {
socks[1] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0) | GETSOCK_READSOCK(1);
}
return GETSOCK_READSOCK(0);
}
/* This is called after the FTP_QUOTE state is passed.
ftp_state_cwd() sends the range of CWD commands to the server to change to
@@ -1382,7 +1370,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data;
if(ftp->transfer != FTPTRANSFER_BODY) {
@@ -1425,7 +1413,7 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
static CURLcode ftp_state_rest(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
@@ -1446,7 +1434,7 @@ static CURLcode ftp_state_rest(struct connectdata *conn)
static CURLcode ftp_state_size(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
@@ -1557,7 +1545,7 @@ static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
static CURLcode ftp_state_type(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -1614,7 +1602,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
bool sizechecked)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
int seekerr = CURL_SEEKFUNC_OK;
@@ -1712,7 +1700,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
bool quote=FALSE;
struct curl_slist *item;
@@ -2058,13 +2046,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
* FTP pointer
*/
struct HTTP http_proxy;
struct FTP *ftp_save = data->state.proto.ftp;
struct FTP *ftp_save = data->req.protop;
memset(&http_proxy, 0, sizeof(http_proxy));
data->state.proto.http = &http_proxy;
data->req.protop = &http_proxy;
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
data->state.proto.ftp = ftp_save;
data->req.protop = ftp_save;
if(result)
return result;
@@ -2124,7 +2112,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
switch(ftpcode) {
@@ -2258,7 +2246,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
@@ -2427,6 +2415,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
if(data->set.ftp_use_port) {
bool connected;
state(conn, FTP_STOP); /* no longer in STOR state */
result = AllowServerConnect(conn, &connected);
if(result)
return result;
@@ -2450,7 +2440,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
char *buf = data->state.buffer;
if((ftpcode == 150) || (ftpcode == 125)) {
@@ -2574,19 +2564,6 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
#ifdef HAVE_KRB4
if(conn->data->set.krb) {
/* We may need to issue a KAUTH here to have access to the files
* do it if user supplied a password
*/
if(conn->passwd && *conn->passwd) {
/* BLOCKING */
result = Curl_krb_kauth(conn);
if(result)
return result;
}
}
#endif
if(conn->ssl[FIRSTSOCKET].use) {
/* PBSZ = PROTECTION BUFFER SIZE.
@@ -2618,7 +2595,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
(void)instate; /* no use for this yet */
@@ -2716,7 +2693,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
/* We have received a 220 response fine, now we proceed. */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
if(data->set.krb) {
/* If not anonymous login, try a secure login. Note that this
procedure is still BLOCKING. */
@@ -3158,56 +3135,6 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
return result;
}
/*
* Allocate and initialize the struct FTP for the current SessionHandle. If
* need be.
*/
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
/* workaround icc 9.1 optimizer issue */
#pragma optimize("", off)
#endif
static CURLcode ftp_init(struct connectdata *conn)
{
struct FTP *ftp;
if(NULL == conn->data->state.proto.ftp) {
conn->data->state.proto.ftp = malloc(sizeof(struct FTP));
if(NULL == conn->data->state.proto.ftp)
return CURLE_OUT_OF_MEMORY;
}
ftp = conn->data->state.proto.ftp;
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->data->req.bytecount;
ftp->transfer = FTPTRANSFER_BODY;
ftp->downloadsize = 0;
/* No need to duplicate user+password, the connectdata struct won't change
during a session, but we re-init them here since on subsequent inits
since the conn struct may have changed or been replaced.
*/
ftp->user = conn->user;
ftp->passwd = conn->passwd;
if(isBadFtpString(ftp->user))
return CURLE_URL_MALFORMAT;
if(isBadFtpString(ftp->passwd))
return CURLE_URL_MALFORMAT;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
return CURLE_OK;
}
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
/* workaround icc 9.1 optimizer issue */
#pragma optimize("", on)
#endif
/*
* ftp_connect() should do everything that is to be considered a part of
* the connection phase.
@@ -3225,14 +3152,6 @@ static CURLcode ftp_connect(struct connectdata *conn,
*done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
result = ftp_init(conn);
if(CURLE_OK != result)
return result;
/* We always support persistent connections on ftp */
conn->bits.close = FALSE;
@@ -3272,7 +3191,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
ssize_t nread;
@@ -3689,7 +3608,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
bool complete = FALSE;
/* the ftp struct is inited in ftp_connect() */
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
/* if the second connection isn't done yet, wait for it */
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
@@ -3837,7 +3756,7 @@ CURLcode ftp_perform(struct connectdata *conn,
if(conn->data->set.opt_no_body) {
/* requested no body means no transfer... */
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
ftp->transfer = FTPTRANSFER_INFO;
}
@@ -4099,17 +4018,6 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */
ftpc->wait_data_conn = FALSE; /* default to no such wait */
/*
Since connections can be re-used between SessionHandles, this might be a
connection already existing but on a fresh SessionHandle struct so we must
make sure we have a good 'struct FTP' to play with. For new connections,
the struct FTP is allocated and setup in the ftp_connect() function.
*/
Curl_reset_reqproto(conn);
retcode = ftp_init(conn);
if(retcode)
return retcode;
if(conn->data->set.wildcardmatch) {
retcode = wc_statemach(conn);
if(conn->data->wildcard.state == CURLWC_SKIP ||
@@ -4141,7 +4049,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
size_t write_len;
char *sptr=s;
CURLcode res = CURLE_OK;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
enum protection_level data_sec = conn->data_prot;
#endif
@@ -4161,12 +4069,12 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
return(res);
for(;;) {
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
#endif
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
&bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
conn->data_prot = data_sec;
#endif
@@ -4268,7 +4176,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
Curl_pp_disconnect(pp);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
Curl_sec_end(conn);
#endif
@@ -4287,7 +4195,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
/* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->state.proto.ftp;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
const char *slash_pos; /* position of the first '/' char in curpos */
const char *path_to_use = data->state.path;
@@ -4342,7 +4250,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
dirlen++;
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? curlx_sztosi(dirlen) : 1,
slash_pos ? curlx_uztosi(dirlen) : 1,
NULL);
if(!ftpc->dirs[0]) {
freedirs(ftpc);
@@ -4477,7 +4385,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
static CURLcode ftp_dophase_done(struct connectdata *conn,
bool connected)
{
struct FTP *ftp = conn->data->state.proto.ftp;
struct FTP *ftp = conn->data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(connected) {
@@ -4577,6 +4485,7 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
struct SessionHandle *data = conn->data;
char *type;
char command;
struct FTP *ftp;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel ftp operations through the proxy, we
@@ -4592,18 +4501,18 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
/*
* We explicitly mark this connection as persistent here as we're doing
* FTP over HTTP and thus we accidentally avoid setting this value
* otherwise.
*/
conn->bits.close = FALSE;
/* set it up as a HTTP connection instead */
return conn->handler->setup_connection(conn);
#else
failf(data, "FTP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
data->state.path++; /* don't include the initial slash */
data->state.slash_removed = TRUE; /* we've skipped the slash */
@@ -4636,6 +4545,24 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
}
}
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->data->req.bytecount;
ftp->transfer = FTPTRANSFER_BODY;
ftp->downloadsize = 0;
/* No need to duplicate user+password, the connectdata struct won't change
during a session, but we re-init them here since on subsequent inits
since the conn struct may have changed or been replaced.
*/
ftp->user = conn->user;
ftp->passwd = conn->passwd;
if(isBadFtpString(ftp->user))
return CURLE_URL_MALFORMAT;
if(isBadFtpString(ftp->passwd))
return CURLE_URL_MALFORMAT;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
return CURLE_OK;
}

View File

@@ -200,6 +200,27 @@ extern sigjmp_buf curl_jmpenv;
*/
CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
/*
* Function provided by the resolver backend to set
* outgoing interface to use for DNS requests
*/
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
const char *interf);
/*
* Function provided by the resolver backend to set
* local IPv4 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
const char *local_ip4);
/*
* Function provided by the resolver backend to set
* local IPv6 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
const char *local_ip6);
/*
* Clean off entries from the cache
*/

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -140,7 +140,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
#if defined(HAVE_GETADDRINFO_THREADSAFE)
else {
struct addrinfo hints;
char sbuf[NI_MAXSERV];
char sbuf[12];
char *sbufptr = NULL;
memset(&hints, 0, sizeof(hints));

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -168,7 +168,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct addrinfo hints;
Curl_addrinfo *res;
int error;
char sbuf[NI_MAXSERV];
char sbuf[12];
char *sbufptr = NULL;
char addrbuf[128];
int pf;

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -72,4 +72,40 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
}
/*
* Function provided by the resolver backend to set
* outgoing interface to use for DNS requests
*/
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
const char *interf)
{
(void)data;
(void)interf;
return CURLE_NOT_BUILT_IN;
}
/*
* Function provided by the resolver backend to set
* local IPv4 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
const char *local_ip4)
{
(void)data;
(void)local_ip4;
return CURLE_NOT_BUILT_IN;
}
/*
* Function provided by the resolver backend to set
* local IPv6 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
const char *local_ip6)
{
(void)data;
(void)local_ip6;
return CURLE_NOT_BUILT_IN;
}
#endif /* truly sync */

View File

@@ -75,6 +75,7 @@
#include "non-ascii.h"
#include "bundles.h"
#include "pipeline.h"
#include "http2.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -105,7 +106,7 @@ static int https_getsock(struct connectdata *conn,
*/
const struct Curl_handler Curl_handler_http = {
"HTTP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_http = {
*/
const struct Curl_handler Curl_handler_https = {
"HTTPS", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -149,6 +150,19 @@ const struct Curl_handler Curl_handler_https = {
#endif
CURLcode Curl_http_setup_conn(struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the SessionHandle, only to survive
during this request */
DEBUGASSERT(conn->data->req.protop == NULL);
conn->data->req.protop = calloc(1, sizeof(struct HTTP));
if(!conn->data->req.protop)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
/*
* checkheaders() checks the linked list of custom HTTP headers for a
* particular header (prefix).
@@ -330,7 +344,7 @@ static bool pickoneauth(struct auth *pick)
static CURLcode http_perhapsrewind(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct HTTP *http = data->state.proto.http;
struct HTTP *http = data->req.protop;
curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */
@@ -948,7 +962,7 @@ static size_t readmoredata(char *buffer,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
struct HTTP *http = conn->data->state.proto.http;
struct HTTP *http = conn->data->req.protop;
size_t fullsize = size * nitems;
if(0 == http->postsize)
@@ -1019,7 +1033,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
CURLcode res;
char *ptr;
size_t size;
struct HTTP *http = conn->data->state.proto.http;
struct HTTP *http = conn->data->req.protop;
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
@@ -1402,7 +1416,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
CURLcode status, bool premature)
{
struct SessionHandle *data = conn->data;
struct HTTP *http =data->state.proto.http;
struct HTTP *http =data->req.protop;
Curl_unencode_cleanup(conn);
@@ -1442,6 +1456,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
if(!premature && /* this check is pointless when DONE is called before the
entire operation is complete */
!conn->bits.retry &&
!data->set.connect_only &&
((http->readbytecount +
data->req.headerbytecount -
data->req.deductheadercount)) <= 0) {
@@ -1456,14 +1471,19 @@ CURLcode Curl_http_done(struct connectdata *conn,
}
/* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it
are if the user specifically requested HTTP 1.0, if the server we are
connected to only supports 1.0, or if any server previously contacted to
handle this request only supports 1.0. */
static bool use_http_1_1(const struct SessionHandle *data,
/*
* Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
* to avoid it include:
*
* - if the user specifically requested HTTP 1.0
* - if the server we are connected to only supports 1.0
* - if any server previously contacted to handle this request only supports
* 1.0.
*/
static bool use_http_1_1plus(const struct SessionHandle *data,
const struct connectdata *conn)
{
return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) ||
return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
((conn->httpversion == 11) ||
((conn->httpversion != 10) &&
@@ -1479,7 +1499,7 @@ static CURLcode expect100(struct SessionHandle *data,
const char *ptr;
data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */
if(use_http_1_1(data, conn)) {
if(use_http_1_1plus(data, conn)) {
/* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
100-continue to the headers which actually speeds up post operations
(as there is one packet coming back from the web server) */
@@ -1655,20 +1675,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the rest of the request in the PERFORM phase. */
*done = TRUE;
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
if(!data->state.proto.http) {
/* Only allocate this struct if we don't already have it! */
http = calloc(1, sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
data->state.proto.http = http;
}
else
http = data->state.proto.http;
http = data->req.protop;
if(!data->state.this_is_a_follow) {
/* this is not a followed location, get the original host name */
@@ -1795,7 +1802,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
;
else if(use_http_1_1(data, conn)) {
else if(use_http_1_1plus(data, conn)) {
/* HTTP, upload, unknown file size and not HTTP 1.0 */
data->req.upload_chunky = TRUE;
}
@@ -2095,7 +2102,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Use 1.1 unless the user specifically asked for 1.0 or the server only
supports 1.0 */
httpstring= use_http_1_1(data, conn)?"1.1":"1.0";
httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
/* initialize a dynamic send-buffer */
req_buffer = Curl_add_buffer_init();
@@ -2173,6 +2180,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result)
return result;
if(!(conn->handler->flags&PROTOPT_SSL) &&
(data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
/* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
over SSL */
result = Curl_http2_request(req_buffer, conn);
if(result)
return result;
}
#if !defined(CURL_DISABLE_COOKIES)
if(data->cookies || addcookies) {
struct Cookie *co=NULL; /* no cookies from start */

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -21,8 +21,14 @@
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"
#ifndef CURL_DISABLE_HTTP
#ifdef USE_NGHTTP2
#include <nghttp2/nghttp2.h>
#endif
extern const struct Curl_handler Curl_handler_http;
#ifdef USE_SSL
@@ -66,6 +72,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
CURLcode Curl_http(struct connectdata *conn, bool *done);
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
CURLcode Curl_http_setup_conn(struct connectdata *conn);
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn);
@@ -141,6 +148,14 @@ struct HTTP {
points to an allocated send_buffer struct */
};
struct http_conn {
#ifdef USE_NGHTTP2
nghttp2_session *h2;
#else
int unused; /* prevent a compiler warning */
#endif
};
CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
struct connectdata *conn,
ssize_t *nread,

182
lib/http2.c Normal file
View File

@@ -0,0 +1,182 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, 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.
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_NGHTTP2
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#include <nghttp2/nghttp2.h>
#include "urldata.h"
#include "http2.h"
#include "http.h"
#include "sendf.h"
#include "curl_base64.h"
#include "curl_memory.h"
/* include memdebug.h last */
#include "memdebug.h"
/*
* Store nghttp2 version info in this buffer, Prefix with a space. Return
* total length written.
*/
int Curl_http2_ver(char *p, size_t len)
{
nghttp2_info *h2 = nghttp2_version(0);
return snprintf(p, len, " nghttp2/%s", h2->version_str);
}
/*
* The implementation of nghttp2_send_callback type. Here we write |data| with
* size |length| to the network and return the number of bytes actually
* written. See the documentation of nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *h2,
const uint8_t *data, size_t length, int flags,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
ssize_t written;
CURLcode rc =
Curl_write(conn, conn->sock[0], data, length, &written);
(void)h2;
(void)flags;
if(rc) {
failf(conn->data, "Failed sending HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
else if(!written)
return NGHTTP2_ERR_WOULDBLOCK;
return written;
}
/*
* The implementation of nghttp2_recv_callback type. Here we read data from
* the network and write them in |buf|. The capacity of |buf| is |length|
* bytes. Returns the number of bytes stored in |buf|. See the documentation
* of nghttp2_recv_callback for the details.
*/
static ssize_t recv_callback(nghttp2_session *h2,
uint8_t *buf, size_t length, int flags,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
ssize_t nread;
CURLcode rc = Curl_read(conn, conn->sock[0], (char *)buf, length, &nread);
(void)h2;
(void)flags;
if(rc) {
failf(conn->data, "Failed recving HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
if(!nread)
return NGHTTP2_ERR_WOULDBLOCK;
return nread;
}
/*
* This is all callbacks nghttp2 calls
*/
static const nghttp2_session_callbacks callbacks = {
send_callback,
recv_callback,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
/*
* The HTTP2 settings we send in the Upgrade request
*/
static nghttp2_settings_entry settings[] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
{ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
};
/*
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
*/
CURLcode Curl_http2_request(Curl_send_buffer *req,
struct connectdata *conn)
{
uint8_t binsettings[80];
CURLcode result;
ssize_t binlen;
char *base64;
size_t blen;
if(!conn->proto.httpc.h2) {
/* The nghttp2 session is not yet setup, do it */
int rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
&callbacks, &conn);
if(rc) {
failf(conn->data, "Couldn't initialize nghttp2!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */
}
}
/* As long as we have a fixed set of settings, we don't have to dynamically
* figure out the base64 strings since it'll always be the same. However,
* the settings will likely not be fixed every time in the future.
*/
/* this returns number of bytes it wrote */
binlen = nghttp2_pack_settings_payload(binsettings,
sizeof(binsettings),
settings,
sizeof(settings)/sizeof(settings[0]));
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
return CURLE_FAILED_INIT;
}
result = Curl_base64_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen);
if(result)
return result;
result = Curl_add_bufferf(req,
"Connection: Upgrade, HTTP2-Settings\r\n"
"Upgrade: %s\r\n"
"HTTP2-Settings: %s\r\n",
NGHTTP2_PROTO_VERSION_ID, base64);
free(base64);
return result;
}
#endif

42
lib/http2.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef HEADER_CURL_HTTP2_H
#define HEADER_CURL_HTTP2_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, 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.
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_NGHTTP2
#include "http.h"
/*
* Store nghttp2 version info in this buffer, Prefix with a space. Return
* total length written.
*/
int Curl_http2_ver(char *p, size_t len);
CURLcode Curl_http2_request(Curl_send_buffer *req,
struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_request(x,y) CURLE_OK
#endif
#endif /* HEADER_CURL_HTTP2_H */

View File

@@ -66,13 +66,13 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
* This function might be called several times in the multi interface case
* if the proxy's CONNTECT response is not instant.
*/
prot_save = conn->data->state.proto.generic;
prot_save = conn->data->req.protop;
memset(&http_proxy, 0, sizeof(http_proxy));
conn->data->state.proto.http = &http_proxy;
conn->data->req.protop = &http_proxy;
conn->bits.close = FALSE;
result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
conn->host.name, conn->remote_port);
conn->data->state.proto.generic = prot_save;
conn->data->req.protop = prot_save;
if(CURLE_OK != result)
return result;
#else

View File

@@ -26,6 +26,7 @@
* RFC4616 PLAIN authentication
* RFC4959 IMAP Extension for SASL Initial Client Response
* RFC5092 IMAP URL Scheme
* RFC6749 OAuth 2.0 Authorization Framework
*
***************************************************************************/
@@ -163,7 +164,7 @@ const struct Curl_handler Curl_handler_imaps = {
static const struct Curl_handler Curl_handler_imap_proxy = {
"IMAP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -188,7 +189,7 @@ static const struct Curl_handler Curl_handler_imap_proxy = {
static const struct Curl_handler Curl_handler_imaps_proxy = {
"IMAPS", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -268,7 +269,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
int *resp)
{
struct IMAP *imap = conn->data->state.proto.imap;
struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
const char *id = imapc->resptag;
size_t id_len = strlen(id);
@@ -307,7 +308,12 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
(strcmp(imap->custom, "STORE") ||
!imap_matchresp(line, len, "FETCH")) &&
strcmp(imap->custom, "SELECT") &&
strcmp(imap->custom, "EXAMINE")))
strcmp(imap->custom, "EXAMINE") &&
strcmp(imap->custom, "SEARCH") &&
strcmp(imap->custom, "EXPUNGE") &&
strcmp(imap->custom, "LSUB") &&
strcmp(imap->custom, "UID") &&
strcmp(imap->custom, "NOOP")))
return FALSE;
break;
@@ -330,7 +336,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
return TRUE;
}
/* Do we have a continuation response? */
/* Do we have a continuation response? This should be a + symbol followed by
a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
some e-mail servers ignore this and only send a single + instead. */
if((len == 3 && !memcmp("+", line, 1)) ||
(len >= 2 && !memcmp("+ ", line, 2))) {
switch(imapc->state) {
@@ -343,6 +352,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
case IMAP_AUTHENTICATE_DIGESTMD5_RESP:
case IMAP_AUTHENTICATE_NTLM:
case IMAP_AUTHENTICATE_NTLM_TYPE2MSG:
case IMAP_AUTHENTICATE_XOAUTH2:
case IMAP_AUTHENTICATE_FINAL:
case IMAP_APPEND:
*resp = '+';
@@ -385,6 +395,7 @@ static void state(struct connectdata *conn, imapstate newstate)
"AUTHENTICATE_DIGESTMD5_RESP",
"AUTHENTICATE_NTLM",
"AUTHENTICATE_NTLM_TYPE2MSG",
"AUTHENTICATE_XOAUTH2",
"AUTHENTICATE_FINAL",
"LOGIN",
"LIST",
@@ -547,13 +558,13 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
#ifndef CURL_DISABLE_CRYPTO_AUTH
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5";
mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = IMAP_AUTHENTICATE_DIGESTMD5;
imapc->authused = SASL_MECH_DIGEST_MD5;
}
else if((imapc->authmechs & SASL_MECH_CRAM_MD5) &&
(imapc->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5";
mech = SASL_MECH_STRING_CRAM_MD5;
state1 = IMAP_AUTHENTICATE_CRAMMD5;
imapc->authused = SASL_MECH_CRAM_MD5;
}
@@ -562,7 +573,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
#ifdef USE_NTLM
if((imapc->authmechs & SASL_MECH_NTLM) &&
(imapc->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM";
mech = SASL_MECH_STRING_NTLM;
state1 = IMAP_AUTHENTICATE_NTLM;
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
imapc->authused = SASL_MECH_NTLM;
@@ -574,9 +585,22 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
}
else
#endif
if((imapc->authmechs & SASL_MECH_LOGIN) &&
if(((imapc->authmechs & SASL_MECH_XOAUTH2) &&
(imapc->prefmech & SASL_MECH_XOAUTH2) &&
(imapc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
state1 = IMAP_AUTHENTICATE_XOAUTH2;
state2 = IMAP_AUTHENTICATE_FINAL;
imapc->authused = SASL_MECH_XOAUTH2;
if(imapc->ir_supported || data->set.sasl_ir)
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&initresp, &len);
}
else if((imapc->authmechs & SASL_MECH_LOGIN) &&
(imapc->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
mech = SASL_MECH_STRING_LOGIN;
state1 = IMAP_AUTHENTICATE_LOGIN;
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
imapc->authused = SASL_MECH_LOGIN;
@@ -587,7 +611,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
}
else if((imapc->authmechs & SASL_MECH_PLAIN) &&
(imapc->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN";
mech = SASL_MECH_STRING_PLAIN;
state1 = IMAP_AUTHENTICATE_PLAIN;
state2 = IMAP_AUTHENTICATE_FINAL;
imapc->authused = SASL_MECH_PLAIN;
@@ -638,7 +662,7 @@ static CURLcode imap_perform_list(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap = data->req.protop;
char *mailbox;
if(imap->custom)
@@ -673,7 +697,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap = data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
char *mailbox;
@@ -712,7 +736,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
static CURLcode imap_perform_fetch(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->state.proto.imap;
struct IMAP *imap = conn->data->req.protop;
/* Check we have a UID */
if(!imap->uid) {
@@ -740,7 +764,7 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
static CURLcode imap_perform_append(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->state.proto.imap;
struct IMAP *imap = conn->data->req.protop;
char *mailbox;
/* Check we have a mailbox */
@@ -864,20 +888,22 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
wordlen -= 5;
/* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
imapc->authmechs |= SASL_MECH_LOGIN;
if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
imapc->authmechs |= SASL_MECH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
imapc->authmechs |= SASL_MECH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
imapc->authmechs |= SASL_MECH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
imapc->authmechs |= SASL_MECH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
imapc->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
imapc->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
imapc->authmechs |= SASL_MECH_XOAUTH2;
}
line += wordlen;
@@ -1243,6 +1269,44 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
}
#endif
/* For AUTH XOAUTH2 (without initial response) responses */
static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *xoauth = NULL;
(void)instate; /* no use for this yet */
if(imapcode != '+') {
failf(data, "Access denied: %d", imapcode);
result = CURLE_LOGIN_DENIED;
}
else {
/* Create the authorisation message */
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&xoauth, &len);
/* Send the message */
if(!result) {
if(xoauth) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL);
}
Curl_safefree(xoauth);
}
}
return result;
}
/* For final responses to the AUTHENTICATE sequence */
static CURLcode imap_state_auth_final_resp(struct connectdata *conn,
int imapcode,
@@ -1316,7 +1380,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = conn->data->state.proto.imap;
struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
char tmp[20];
@@ -1407,10 +1471,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
return result;
data->req.bytecount += chunk;
size -= chunk;
infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU
" bytes are left for transfer\n", (curl_off_t)chunk, size);
" bytes are left for transfer\n", (curl_off_t)chunk,
size - chunk);
/* Have we used the entire cache or just part of it?*/
if(pp->cache_size > chunk) {
@@ -1427,7 +1491,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
}
}
if(!size)
if(data->req.bytecount == size)
/* The entire data is already transferred! */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
else {
@@ -1592,6 +1656,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
break;
#endif
case IMAP_AUTHENTICATE_XOAUTH2:
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
break;
case IMAP_AUTHENTICATE_FINAL:
result = imap_state_auth_final_resp(conn, imapcode, imapc->state);
break;
@@ -1642,11 +1710,13 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone)
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
else
result = Curl_pp_statemach(&imapc->pp, FALSE);
if(result || !imapc->ssldone)
return result;
}
result = Curl_pp_statemach(&imapc->pp, FALSE);
*done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
return result;
@@ -1669,13 +1739,11 @@ static CURLcode imap_init(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap;
if(!imap) {
imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1);
imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
if(!imap)
result = CURLE_OUT_OF_MEMORY;
}
return result;
}
@@ -1705,15 +1773,6 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
*done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
/* Initialise the IMAP layer */
result = imap_init(conn);
if(result)
return result;
/* We always support persistent connections in IMAP */
conn->bits.close = FALSE;
@@ -1759,7 +1818,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap = data->req.protop;
(void)premature;
@@ -1824,7 +1883,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
/* This is IMAP and no proxy */
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap = data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
bool selected = FALSE;
@@ -1891,15 +1950,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */
/* Since connections can be re-used between SessionHandles, there might be a
connection already existing but on a fresh SessionHandle struct. As such
we make sure we have a good IMAP struct to play with. For new connections
the IMAP struct is allocated and setup in the imap_connect() function. */
Curl_reset_reqproto(conn);
result = imap_init(conn);
if(result)
return result;
/* Parse the URL path */
result = imap_parse_url_path(conn);
if(result)
@@ -1952,7 +2002,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
/* Call this when the DO phase has completed */
static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
{
struct IMAP *imap = conn->data->state.proto.imap;
struct IMAP *imap = conn->data->req.protop;
(void)connected;
@@ -2018,6 +2068,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
/* Initialise the IMAP layer */
CURLcode result = imap_init(conn);
if(result)
return result;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel IMAP operations through the proxy, we
switch and use HTTP operations only */
@@ -2033,10 +2088,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
#endif
}
/* We explicitly mark this connection as persistent here as we're doing
IMAP over HTTP and thus we accidentally avoid setting this value
otherwise */
conn->bits.close = FALSE;
/* set it up as an HTTP connection instead */
return conn->handler->setup_connection(conn);
#else
failf(data, "IMAP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
@@ -2225,18 +2278,20 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
if(strequal(value, "*"))
imapc->prefmech = SASL_AUTH_ANY;
else if(strequal(value, "LOGIN"))
else if(strequal(value, SASL_MECH_STRING_LOGIN))
imapc->prefmech = SASL_MECH_LOGIN;
else if(strequal(value, "PLAIN"))
else if(strequal(value, SASL_MECH_STRING_PLAIN))
imapc->prefmech = SASL_MECH_PLAIN;
else if(strequal(value, "CRAM-MD5"))
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5))
imapc->prefmech = SASL_MECH_CRAM_MD5;
else if(strequal(value, "DIGEST-MD5"))
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5))
imapc->prefmech = SASL_MECH_DIGEST_MD5;
else if(strequal(value, "GSSAPI"))
else if(strequal(value, SASL_MECH_STRING_GSSAPI))
imapc->prefmech = SASL_MECH_GSSAPI;
else if(strequal(value, "NTLM"))
else if(strequal(value, SASL_MECH_STRING_NTLM))
imapc->prefmech = SASL_MECH_NTLM;
else if(strequal(value, SASL_MECH_STRING_XOAUTH2))
imapc->prefmech = SASL_MECH_XOAUTH2;
else
imapc->prefmech = SASL_AUTH_NONE;
}
@@ -2259,7 +2314,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
/* The imap struct is already initialised in imap_connect() */
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap = data->req.protop;
const char *begin = data->state.path;
const char *ptr = begin;
@@ -2367,7 +2422,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap;
struct IMAP *imap = data->req.protop;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
if(custom) {

View File

@@ -43,6 +43,7 @@ typedef enum {
IMAP_AUTHENTICATE_DIGESTMD5_RESP,
IMAP_AUTHENTICATE_NTLM,
IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
IMAP_AUTHENTICATE_XOAUTH2,
IMAP_AUTHENTICATE_FINAL,
IMAP_LOGIN,
IMAP_LIST,

View File

@@ -1,440 +0,0 @@
/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
* use in Curl. Martin's latest changes were done 2000-09-18.
*
* It has since been patched away like a madman by Daniel Stenberg to make it
* better applied to curl conditions, and to make it not use globals, pollute
* name space and more.
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* Copyright (c) 2004 - 2011 Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "curl_setup.h"
#ifndef CURL_DISABLE_FTP
#ifdef HAVE_KRB4
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <krb.h>
#include <des.h>
#include "urldata.h"
#include "curl_base64.h"
#include "ftp.h"
#include "sendf.h"
#include "krb4.h"
#include "inet_ntop.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#define LOCAL_ADDR (&conn->local_addr)
#define REMOTE_ADDR conn->ip_addr->ai_addr
#define myctladdr LOCAL_ADDR
#define hisctladdr REMOTE_ADDR
struct krb4_data {
des_cblock key;
des_key_schedule schedule;
char name[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
};
#ifndef HAVE_STRLCPY
/* if it ever goes non-static, make it Curl_ prefixed! */
static size_t
strlcpy (char *dst, const char *src, size_t dst_sz)
{
size_t n;
char *p;
for(p = dst, n = 0;
n + 1 < dst_sz && *src != '\0';
++p, ++src, ++n)
*p = *src;
*p = '\0';
if(*src == '\0')
return n;
else
return n + strlen (src);
}
#else
size_t strlcpy (char *dst, const char *src, size_t dst_sz);
#endif
static int
krb4_check_prot(void *app_data, int level)
{
app_data = NULL; /* prevent compiler warning */
if(level == PROT_CONFIDENTIAL)
return -1;
return 0;
}
static int
krb4_decode(void *app_data, void *buf, int len, int level,
struct connectdata *conn)
{
MSG_DAT m;
int e;
struct krb4_data *d = app_data;
if(level == PROT_SAFE)
e = krb_rd_safe(buf, len, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
else
e = krb_rd_priv(buf, len, d->schedule, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
if(e) {
struct SessionHandle *data = conn->data;
infof(data, "krb4_decode: %s\n", krb_get_err_text(e));
return -1;
}
memmove(buf, m.app_data, m.app_length);
return m.app_length;
}
static int
krb4_overhead(void *app_data, int level, int len)
{
/* no arguments are used, just init them to prevent compiler warnings */
app_data = NULL;
level = 0;
len = 0;
return 31;
}
static int
krb4_encode(void *app_data, const void *from, int length, int level, void **to,
struct connectdata *conn)
{
struct krb4_data *d = app_data;
*to = malloc(length + 31);
if(!*to)
return -1;
if(level == PROT_SAFE)
/* NOTE that the void* cast is safe, krb_mk_safe/priv don't modify the
* input buffer
*/
return krb_mk_safe((void*)from, *to, length, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else if(level == PROT_PRIVATE)
return krb_mk_priv((void*)from, *to, length, d->schedule, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else
return -1;
}
static int
mk_auth(struct krb4_data *d, KTEXT adat,
const char *service, char *host, int checksum)
{
int ret;
CREDENTIALS cred;
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_mk_req(adat, sname, inst, realm, checksum);
if(ret)
return ret;
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_get_cred(sname, inst, realm, &cred);
memmove(&d->key, &cred.session, sizeof(des_cblock));
des_key_sched(&d->key, d->schedule);
memset(&cred, 0, sizeof(cred));
return ret;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
int krb_get_our_ip_for_realm(char *, struct in_addr *);
#endif
static int
krb4_auth(void *app_data, struct connectdata *conn)
{
int ret;
char *p;
unsigned char *ptr;
size_t len = 0;
KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
u_int32_t cs;
struct krb4_data *d = app_data;
char *host = conn->host.name;
ssize_t nread;
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
CURLcode result;
size_t base64_sz = 0;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()");
checksum = getpid();
ret = mk_auth(d, &adat, "ftp", host, checksum);
if(ret == KDC_PR_UNKNOWN)
ret = mk_auth(d, &adat, "rcmd", host, checksum);
if(ret) {
infof(data, "%s\n", krb_get_err_text(ret));
return AUTH_CONTINUE;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
if(krb_get_config_bool("nat_in_use")) {
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
struct in_addr natAddr;
if(krb_get_our_ip_for_realm(krb_realmofhost(host),
&natAddr) != KSUCCESS
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
infof(data, "Can't get address for realm %s\n",
krb_realmofhost(host));
else {
if(natAddr.s_addr != localaddr->sin_addr.s_addr) {
char addr_buf[128];
if(Curl_inet_ntop(AF_INET, natAddr, addr_buf, sizeof(addr_buf)))
infof(data, "Using NAT IP address (%s) for kerberos 4\n", addr_buf);
localaddr->sin_addr = natAddr;
}
}
}
#endif
result = Curl_base64_encode(conn->data, (char *)adat.dat, adat.length,
&p, &base64_sz);
if(result) {
Curl_failf(data, "base64-encoding: %s", curl_easy_strerror(result));
return AUTH_CONTINUE;
}
result = Curl_ftpsendf(conn, "ADAT %s", p);
free(p);
if(result)
return -2;
if(Curl_GetFTPResponse(&nread, conn, NULL))
return -1;
if(data->state.buffer[0] != '2') {
Curl_failf(data, "Server didn't accept auth data");
return AUTH_ERROR;
}
p = strstr(data->state.buffer, "ADAT=");
if(!p) {
Curl_failf(data, "Remote host didn't send adat reply");
return AUTH_ERROR;
}
p += 5;
result = Curl_base64_decode(p, &ptr, &len);
if(result) {
Curl_failf(data, "base64-decoding: %s", curl_easy_strerror(result));
return AUTH_ERROR;
}
if(len > sizeof(adat.dat)-1) {
free(ptr);
ptr = NULL;
len = 0;
}
if(!len || !ptr) {
Curl_failf(data, "Failed to decode base64 from server");
return AUTH_ERROR;
}
memcpy((char *)adat.dat, ptr, len);
free(ptr);
adat.length = len;
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr,
(struct sockaddr_in *)myctladdr, &msg_data);
if(ret) {
Curl_failf(data, "Error reading reply from server: %s",
krb_get_err_text(ret));
return AUTH_ERROR;
}
krb_get_int(msg_data.app_data, &cs, 4, 0);
if(cs - checksum != 1) {
Curl_failf(data, "Bad checksum returned from server");
return AUTH_ERROR;
}
return AUTH_OK;
}
struct Curl_sec_client_mech Curl_krb4_client_mech = {
"KERBEROS_V4",
sizeof(struct krb4_data),
NULL, /* init */
krb4_auth,
NULL, /* end */
krb4_check_prot,
krb4_overhead,
krb4_encode,
krb4_decode
};
static enum protection_level
krb4_set_command_prot(struct connectdata *conn, enum protection_level level)
{
enum protection_level old = conn->command_prot;
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
conn->command_prot = level;
return old;
}
CURLcode Curl_krb_kauth(struct connectdata *conn)
{
des_cblock key;
des_key_schedule schedule;
KTEXT_ST tkt, tktcopy;
char *name;
char *p;
char passwd[100];
size_t tmp = 0;
ssize_t nread;
enum protection_level save;
CURLcode result;
unsigned char *ptr;
size_t base64_sz = 0;
save = krb4_set_command_prot(conn, PROT_PRIVATE);
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user);
if(result)
return result;
result = Curl_GetFTPResponse(&nread, conn, NULL);
if(result)
return result;
if(conn->data->state.buffer[0] != '3') {
krb4_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
p = strstr(conn->data->state.buffer, "T=");
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
krb4_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
p += 2;
result = Curl_base64_decode(p, &ptr, &tmp);
if(result) {
Curl_failf(conn->data, "base64-decoding: %s", curl_easy_strerror(result));
return result;
}
if(tmp >= sizeof(tkt.dat)) {
free(ptr);
ptr = NULL;
tmp = 0;
}
if(!tmp || !ptr) {
Curl_failf(conn->data, "Failed to decode base64 in reply");
krb4_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
memcpy((char *)tkt.dat, ptr, tmp);
free(ptr);
tkt.length = tmp;
tktcopy.length = tkt.length;
p = strstr(conn->data->state.buffer, "P=");
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
krb4_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
name = p + 2;
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
*p = 0;
des_string_to_key (conn->passwd, &key);
des_key_sched(&key, schedule);
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
if(strcmp ((char*)tktcopy.dat + 8,
KRB_TICKET_GRANTING_TICKET) != 0) {
afs_string_to_key(passwd,
krb_realmofhost(conn->host.name),
&key);
des_key_sched(&key, schedule);
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
}
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
result = Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length,
&p, &base64_sz);
if(result) {
Curl_failf(conn->data, "base64-encoding: %s", curl_easy_strerror(result));
krb4_set_command_prot(conn, save);
return result;
}
memset (tktcopy.dat, 0, tktcopy.length);
result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p);
free(p);
if(result)
return result;
result = Curl_GetFTPResponse(&nread, conn, NULL);
if(result)
return result;
krb4_set_command_prot(conn, save);
return CURLE_OK;
}
#endif /* HAVE_KRB4 */
#endif /* CURL_DISABLE_FTP */

View File

@@ -1,6 +1,6 @@
/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2013 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* Copyright (c) 2004 - 2012 Daniel Stenberg
* All rights reserved.
@@ -51,7 +51,7 @@
#include "ftp.h"
#include "curl_gssapi.h"
#include "sendf.h"
#include "krb4.h"
#include "curl_sec.h"
#include "curl_memory.h"
#include "warnless.h"

View File

@@ -84,6 +84,9 @@ typedef struct {
int lud_scope;
char *lud_filter;
char **lud_exts;
size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the
"real" struct so can only be used in code
without HAVE_LDAP_URL_PARSE defined */
} CURL_LDAPURLDesc;
#undef LDAPURLDesc
@@ -539,19 +542,15 @@ static bool unescape_elements (void *data, LDAPURLDesc *ludp)
if(ludp->lud_filter) {
ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL);
if(!ludp->lud_filter)
return (FALSE);
return FALSE;
}
for(i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i], 0, NULL);
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i],
0, NULL);
if(!ludp->lud_attrs[i])
return (FALSE);
}
for(i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) {
ludp->lud_exts[i] = curl_easy_unescape(data, ludp->lud_exts[i], 0, NULL);
if(!ludp->lud_exts[i])
return (FALSE);
return FALSE;
ludp->lud_attrs_dups++;
}
if(ludp->lud_dn) {
@@ -637,8 +636,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p && *p != '?') {
ludp->lud_scope = str2scope(p);
if(ludp->lud_scope == -1)
if(ludp->lud_scope == -1) {
return LDAP_INVALID_SYNTAX;
}
LDAP_TRACE (("scope %d\n", ludp->lud_scope));
}
@@ -651,25 +651,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
q = strchr(p, '?');
if(q)
*q++ = '\0';
if(!*p)
if(!*p) {
return LDAP_INVALID_SYNTAX;
}
ludp->lud_filter = p;
LDAP_TRACE (("filter '%s'\n", ludp->lud_filter));
p = q;
if(!p)
goto success;
/* parse extensions
*/
ludp->lud_exts = split_str(p);
if(!ludp->lud_exts)
return LDAP_NO_MEMORY;
for(i = 0; ludp->lud_exts[i]; i++)
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
success:
if(!unescape_elements(conn->data, ludp))
return LDAP_NO_MEMORY;
@@ -697,7 +685,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
static void _ldap_free_urldesc (LDAPURLDesc *ludp)
{
int i;
size_t i;
if(!ludp)
return;
@@ -709,16 +697,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp)
free(ludp->lud_filter);
if(ludp->lud_attrs) {
for(i = 0; ludp->lud_attrs[i]; i++)
for(i = 0; i < ludp->lud_attrs_dups; i++)
free(ludp->lud_attrs[i]);
free(ludp->lud_attrs);
}
if(ludp->lud_exts) {
for(i = 0; ludp->lud_exts[i]; i++)
free(ludp->lud_exts[i]);
free(ludp->lud_exts);
}
free (ludp);
}
#endif /* !HAVE_LDAP_URL_PARSE */

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,13 @@
*
***************************************************************************/
/* See multi_socket() for the explanation of this constant. Counted in number
of microseconds. */
#ifdef WIN32
#define MULTI_TIMEOUT_INACCURACY 40000
#else
#define MULTI_TIMEOUT_INACCURACY 3000
#endif
/*
* Prototypes for library-wide functions provided by multi.c

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -50,15 +50,18 @@ enum host_lookup_state {
/*
* @unittest: 1304
*
* *loginp and *passwordp MUST be allocated if they aren't NULL when passed
* in.
*/
int Curl_parsenetrc(const char *host,
char *login,
char *password,
char **loginp,
char **passwordp,
char *netrcfile)
{
FILE *file;
int retcode=1;
int specific_login = (login[0] != 0);
int specific_login = (**loginp != 0);
char *home = NULL;
bool home_alloc = FALSE;
bool netrc_alloc = FALSE;
@@ -109,7 +112,7 @@ int Curl_parsenetrc(const char *host,
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
while(!done && tok) {
if(login[0] && password[0]) {
if(**loginp && **passwordp) {
done=TRUE;
break;
}
@@ -138,16 +141,22 @@ int Curl_parsenetrc(const char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
state_our_login = Curl_raw_equal(login, tok);
state_our_login = Curl_raw_equal(*loginp, tok);
}
else {
strncpy(login, tok, LOGINSIZE-1);
free(*loginp);
*loginp = strdup(tok);
if(!*loginp)
return -1; /* allocation failed */
}
state_login=0;
}
else if(state_password) {
if(state_our_login || !specific_login) {
strncpy(password, tok, PASSWORDSIZE-1);
free(*passwordp);
*passwordp = strdup(tok);
if(!*passwordp)
return -1; /* allocation failed */
}
state_password=0;
}

View File

@@ -22,19 +22,15 @@
*
***************************************************************************/
/* Make sure we have room for at least this size: */
#define LOGINSIZE 64
#define PASSWORDSIZE 64
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
int Curl_parsenetrc(const char *host,
char *login,
char *password,
char **loginp,
char **passwordp,
char *filename);
/* Assume: password[0]=0, host[0] != 0.
* If login[0] = 0, search for login and password within a machine section
* in the netrc.
* If login[0] != 0, search for password within machine and login.
/* Assume: (*passwordp)[0]=0, host[0] != 0.
* If (*loginp)[0] = 0, search for login and password within a machine
* section in the netrc.
* If (*loginp)[0] != 0, search for password within machine and login.
*/
#endif /* HEADER_CURL_NETRC_H */

View File

@@ -1543,9 +1543,8 @@ size_t Curl_nss_version(char *buffer, size_t size)
int Curl_nss_seed(struct SessionHandle *data)
{
/* TODO: implement? */
(void) data;
return 0;
/* make sure that NSS is initialized */
return !!Curl_nss_force_init(data);
}
void Curl_nss_random(struct SessionHandle *data,
@@ -1553,7 +1552,11 @@ void Curl_nss_random(struct SessionHandle *data,
size_t length)
{
Curl_nss_seed(data); /* Initiate the seed if not already done */
PK11_GenerateRandom(entropy, curlx_uztosi(length));
if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) {
/* no way to signal a failure from here, we have to abort */
failf(data, "PK11_GenerateRandom() failed, calling abort()...");
abort();
}
}
void Curl_nss_md5sum(unsigned char *tmp, /* input */

View File

@@ -378,7 +378,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
if(!lr)
return CURLE_OUT_OF_MEMORY;
lr->msgid = msgid;
data->state.proto.generic = lr;
data->req.protop = lr;
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
*done = TRUE;
return CURLE_OK;
@@ -387,7 +387,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
bool premature)
{
ldapreqinfo *lr = conn->data->state.proto.generic;
ldapreqinfo *lr = conn->data->req.protop;
(void)res;
(void)premature;
@@ -398,7 +398,7 @@ static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
lr->msgid = 0;
}
conn->data->state.proto.generic = NULL;
conn->data->req.protop = NULL;
free(lr);
}
return CURLE_OK;
@@ -409,7 +409,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
{
ldapconninfo *li = conn->proto.generic;
struct SessionHandle *data=conn->data;
ldapreqinfo *lr = data->state.proto.generic;
ldapreqinfo *lr = data->req.protop;
int rc, ret;
LDAPMessage *result = NULL;
LDAPMessage *ent;

View File

@@ -33,6 +33,7 @@
#include "pingpong.h"
#include "multiif.h"
#include "non-ascii.h"
#include "sslgen.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -105,6 +106,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
if(Curl_pp_moredata(pp))
/* We are receiving and there is data in the cache so just read it */
rc = 1;
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
/* We are receiving and there is data ready in the SSL library */
rc = 1;
else
rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
@@ -165,7 +169,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
enum protection_level data_sec = conn->data_prot;
#endif
@@ -194,12 +198,12 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
return error;
}
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
#endif
error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
&bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
conn->data_prot = data_sec;
#endif
@@ -302,14 +306,14 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
}
else {
int res;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
enum protection_level prot = conn->data_prot;
conn->data_prot = PROT_CLEAR;
#endif
DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
&gotbytes);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
conn->data_prot = prot;
#endif
@@ -352,7 +356,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
the line isn't really terminated until the LF comes */
/* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
if(!conn->sec_complete)
#endif
if(data->set.verbose)
@@ -371,8 +375,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
/* This is the end of the last line, copy the last line to the
start of the buffer and zero terminate, for old times sake (and
krb4)! */
start of the buffer and zero terminate, for old times sake */
char *meow;
int n;
for(meow=pp->linestart_resp, n=0; meow<ptr; meow++, n++)

View File

@@ -28,6 +28,7 @@
* RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication
* RFC5034 POP3 SASL Authentication Mechanism
* RFC6749 OAuth 2.0 Authorization Framework
*
***************************************************************************/
@@ -163,7 +164,7 @@ const struct Curl_handler Curl_handler_pop3s = {
static const struct Curl_handler Curl_handler_pop3_proxy = {
"POP3", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -188,7 +189,7 @@ static const struct Curl_handler Curl_handler_pop3_proxy = {
static const struct Curl_handler Curl_handler_pop3s_proxy = {
"POP3S", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -312,20 +313,22 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
wordlen++;
/* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
pop3c->authmechs |= SASL_MECH_LOGIN;
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
pop3c->authmechs |= SASL_MECH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
pop3c->authmechs |= SASL_MECH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
pop3c->authmechs |= SASL_MECH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
pop3c->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
pop3c->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
pop3c->authmechs |= SASL_MECH_XOAUTH2;
line += wordlen;
len -= wordlen;
@@ -371,6 +374,7 @@ static void state(struct connectdata *conn, pop3state newstate)
"AUTH_DIGESTMD5_RESP",
"AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG",
"AUTH_XOAUTH2",
"AUTH_FINAL",
"APOP",
"USER",
@@ -572,13 +576,13 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
#ifndef CURL_DISABLE_CRYPTO_AUTH
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5";
mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = POP3_AUTH_DIGESTMD5;
pop3c->authused = SASL_MECH_DIGEST_MD5;
}
else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
(pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5";
mech = SASL_MECH_STRING_CRAM_MD5;
state1 = POP3_AUTH_CRAMMD5;
pop3c->authused = SASL_MECH_CRAM_MD5;
}
@@ -587,7 +591,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
#ifdef USE_NTLM
if((pop3c->authmechs & SASL_MECH_NTLM) &&
(pop3c->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM";
mech = SASL_MECH_STRING_NTLM;
state1 = POP3_AUTH_NTLM;
state2 = POP3_AUTH_NTLM_TYPE2MSG;
pop3c->authused = SASL_MECH_NTLM;
@@ -599,9 +603,22 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
}
else
#endif
if((pop3c->authmechs & SASL_MECH_LOGIN) &&
if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
(pop3c->prefmech & SASL_MECH_XOAUTH2) &&
(pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
state1 = POP3_AUTH_XOAUTH2;
state2 = POP3_AUTH_FINAL;
pop3c->authused = SASL_MECH_XOAUTH2;
if(data->set.sasl_ir)
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&initresp, &len);
}
else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
(pop3c->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
mech = SASL_MECH_STRING_LOGIN;
state1 = POP3_AUTH_LOGIN;
state2 = POP3_AUTH_LOGIN_PASSWD;
pop3c->authused = SASL_MECH_LOGIN;
@@ -612,7 +629,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
}
else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
(pop3c->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN";
mech = SASL_MECH_STRING_PLAIN;
state1 = POP3_AUTH_PLAIN;
state2 = POP3_AUTH_FINAL;
pop3c->authused = SASL_MECH_PLAIN;
@@ -673,7 +690,7 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
struct POP3 *pop3 = data->req.protop;
const char *command = NULL;
/* Calculate the default command */
@@ -1110,6 +1127,43 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
}
#endif
/* For AUTH XOAUTH2 (without initial response) responses */
static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
int pop3code, pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *xoauth = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
/* Create the authorisation message */
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&xoauth, &len);
/* Send the message */
if(!result) {
if(xoauth) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
if(!result)
state(conn, POP3_AUTH_FINAL);
}
Curl_safefree(xoauth);
}
}
return result;
}
/* For final responses to the AUTH sequence */
static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
int pop3code,
@@ -1203,7 +1257,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
struct POP3 *pop3 = data->req.protop;
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp;
@@ -1328,6 +1382,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
break;
#endif
case POP3_AUTH_XOAUTH2:
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
break;
case POP3_AUTH_FINAL:
result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
break;
@@ -1368,11 +1426,13 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone)
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
else
result = Curl_pp_statemach(&pop3c->pp, FALSE);
if(result || !pop3c->ssldone)
return result;
}
result = Curl_pp_statemach(&pop3c->pp, FALSE);
*done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
return result;
@@ -1395,13 +1455,11 @@ static CURLcode pop3_init(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
struct POP3 *pop3;
if(!pop3) {
pop3 = data->state.proto.pop3 = calloc(sizeof(struct POP3), 1);
pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
if(!pop3)
result = CURLE_OUT_OF_MEMORY;
}
return result;
}
@@ -1431,15 +1489,6 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
*done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
/* Initialise the POP3 layer */
result = pop3_init(conn);
if(result)
return result;
/* We always support persistent connections in POP3 */
conn->bits.close = FALSE;
@@ -1483,7 +1532,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
struct POP3 *pop3 = data->req.protop;
(void)premature;
@@ -1526,7 +1575,7 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
if(conn->data->set.opt_no_body) {
/* Requested no body means no transfer */
struct POP3 *pop3 = conn->data->state.proto.pop3;
struct POP3 *pop3 = conn->data->req.protop;
pop3->transfer = FTPTRANSFER_INFO;
}
@@ -1563,15 +1612,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */
/* Since connections can be re-used between SessionHandles, there might be a
connection already existing but on a fresh SessionHandle struct. As such
we make sure we have a good POP3 struct to play with. For new connections
the POP3 struct is allocated and setup in the pop3_connect() function. */
Curl_reset_reqproto(conn);
result = pop3_init(conn);
if(result)
return result;
/* Parse the URL path */
result = pop3_parse_url_path(conn);
if(result)
@@ -1685,6 +1725,11 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
/* Initialise the POP3 layer */
CURLcode result = pop3_init(conn);
if(result)
return result;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel POP3 operations through the proxy, we
switch and use HTTP operations only */
@@ -1700,10 +1745,8 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
#endif
}
/* We explicitly mark this connection as persistent here as we're doing
POP3 over HTTP and thus we accidentally avoid setting this value
otherwise */
conn->bits.close = FALSE;
/* set it up as an HTTP connection instead */
return conn->handler->setup_connection(conn);
#else
failf(data, "POP3 over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
@@ -1745,30 +1788,34 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
pop3c->preftype = POP3_TYPE_APOP;
pop3c->prefmech = SASL_AUTH_NONE;
}
else if(strequal(value, "LOGIN")) {
else if(strequal(value, SASL_MECH_STRING_LOGIN)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_LOGIN;
}
else if(strequal(value, "PLAIN")) {
else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_PLAIN;
}
else if(strequal(value, "CRAM-MD5")) {
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_CRAM_MD5;
}
else if(strequal(value, "DIGEST-MD5")) {
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_DIGEST_MD5;
}
else if(strequal(value, "GSSAPI")) {
else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_GSSAPI;
}
else if(strequal(value, "NTLM")) {
else if(strequal(value, SASL_MECH_STRING_NTLM)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_NTLM;
}
else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_XOAUTH2;
}
else {
pop3c->preftype = POP3_TYPE_NONE;
pop3c->prefmech = SASL_AUTH_NONE;
@@ -1791,7 +1838,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
{
/* The POP3 struct is already initialised in pop3_connect() */
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
struct POP3 *pop3 = data->req.protop;
const char *path = data->state.path;
/* URL decode the path for the message ID */
@@ -1808,7 +1855,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
struct POP3 *pop3 = data->req.protop;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */

View File

@@ -43,6 +43,7 @@ typedef enum {
POP3_AUTH_DIGESTMD5_RESP,
POP3_AUTH_NTLM,
POP3_AUTH_NTLM_TYPE2MSG,
POP3_AUTH_XOAUTH2,
POP3_AUTH_FINAL,
POP3_APOP,
POP3_USER,

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -81,6 +81,8 @@ static CURLcode rtsp_rtp_readwrite(struct SessionHandle *data,
ssize_t *nread,
bool *readmore);
static CURLcode rtsp_setup_connection(struct connectdata *conn);
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
@@ -104,7 +106,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
*/
const struct Curl_handler Curl_handler_rtsp = {
"RTSP", /* scheme */
ZERO_NULL, /* setup_connection */
rtsp_setup_connection, /* setup_connection */
rtsp_do, /* do_it */
rtsp_done, /* done */
ZERO_NULL, /* do_more */
@@ -122,6 +124,19 @@ const struct Curl_handler Curl_handler_rtsp = {
PROTOPT_NONE /* flags */
};
static CURLcode rtsp_setup_connection(struct connectdata *conn)
{
struct RTSP *rtsp;
conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
/*
* The server may send us RTP data at any point, and RTSPREQ_RECEIVE does not
* want to block the application forever while receiving a stream. Therefore,
@@ -185,7 +200,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
CURLcode status, bool premature)
{
struct SessionHandle *data = conn->data;
struct RTSP *rtsp = data->state.proto.rtsp;
struct RTSP *rtsp = data->req.protop;
CURLcode httpStatus;
long CSeq_sent;
long CSeq_recv;
@@ -221,7 +236,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
struct SessionHandle *data = conn->data;
CURLcode result=CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp;
struct RTSP *rtsp = data->req.protop;
struct HTTP *http;
Curl_send_buffer *req_buffer;
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -239,20 +254,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
*done = TRUE;
Curl_reset_reqproto(conn);
if(!data->state.proto.rtsp) {
/* Only allocate this struct if we don't already have it! */
rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
data->state.proto.rtsp = rtsp;
}
else {
rtsp = data->state.proto.rtsp;
}
http = &(rtsp->http_wrapper);
/* Assert that no one has changed the RTSP struct in an evil way */
DEBUGASSERT((void *)http == (void *)rtsp);
@@ -749,7 +750,8 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
/* Store the received CSeq. Match is verified in rtsp_done */
int nc = sscanf(&header[4], ": %ld", &CSeq);
if(nc == 1) {
data->state.proto.rtsp->CSeq_recv = CSeq; /* mark the request */
struct RTSP *rtsp = data->req.protop;
rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
}
else {

View File

@@ -7,7 +7,7 @@
* rewrite to work around the paragraph 2 in the BSD licenses as explained
* below.
*
* Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan
* Copyright (c) 1998, 1999, 2013 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
*
* Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
@@ -44,7 +44,7 @@
#include "curl_setup.h"
#ifndef CURL_DISABLE_FTP
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
#ifdef HAVE_NETDB_H
#include <netdb.h>
@@ -57,7 +57,7 @@
#include "urldata.h"
#include "curl_base64.h"
#include "curl_memory.h"
#include "krb4.h"
#include "curl_sec.h"
#include "ftp.h"
#include "sendf.h"
#include "rawstr.h"
@@ -110,11 +110,8 @@ static char level_to_char(int level) {
}
static const struct Curl_sec_client_mech * const mechs[] = {
#if defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
&Curl_krb5_client_mech,
#endif
#if defined(HAVE_KRB4)
&Curl_krb4_client_mech,
#endif
NULL
};
@@ -199,7 +196,7 @@ socket_write(struct connectdata *conn, curl_socket_t fd, const void *to,
static CURLcode read_data(struct connectdata *conn,
curl_socket_t fd,
struct krb4buffer *buf)
struct krb5buffer *buf)
{
int len;
void* tmp;
@@ -225,7 +222,7 @@ static CURLcode read_data(struct connectdata *conn,
}
static size_t
buffer_read(struct krb4buffer *buf, void *data, size_t len)
buffer_read(struct krb5buffer *buf, void *data, size_t len)
{
if(buf->size - buf->index < len)
len = buf->size - buf->index;
@@ -599,6 +596,6 @@ Curl_sec_end(struct connectdata *conn)
conn->mech = NULL;
}
#endif /* HAVE_KRB4 || HAVE_GSSAPI */
#endif /* HAVE_GSSAPI */
#endif /* CURL_DISABLE_FTP */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,14 +35,6 @@
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
/* the krb4 functions only exists for FTP and if krb4 or gssapi is defined */
#if !defined(CURL_DISABLE_FTP) && (defined(HAVE_KRB4) || defined(HAVE_GSSAPI))
#include "krb4.h"
#else
#define Curl_sec_send(a,b,c,d) -1
#define Curl_sec_read(a,b,c,d) -1
#endif
#include "curl_memory.h"
#include "strerror.h"

View File

@@ -26,6 +26,7 @@
* RFC4616 PLAIN authentication
* RFC4954 SMTP Authentication
* RFC5321 SMTP protocol
* RFC6749 OAuth 2.0 Authorization Framework
* Draft SMTP URL Interface
*
***************************************************************************/
@@ -161,7 +162,7 @@ const struct Curl_handler Curl_handler_smtps = {
static const struct Curl_handler Curl_handler_smtp_proxy = {
"SMTP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -186,7 +187,7 @@ static const struct Curl_handler Curl_handler_smtp_proxy = {
static const struct Curl_handler Curl_handler_smtps_proxy = {
"SMTPS", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -276,20 +277,22 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
wordlen++;
/* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
smtpc->authmechs |= SASL_MECH_LOGIN;
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
smtpc->authmechs |= SASL_MECH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
smtpc->authmechs |= SASL_MECH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
smtpc->authmechs |= SASL_MECH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
smtpc->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4))
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
smtpc->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
smtpc->authmechs |= SASL_MECH_XOAUTH2;
line += wordlen;
len -= wordlen;
@@ -326,6 +329,7 @@ static void state(struct connectdata *conn, smtpstate newstate)
"AUTH_DIGESTMD5_RESP",
"AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG",
"AUTH_XOAUTH2",
"AUTH_FINAL",
"MAIL",
"RCPT",
@@ -469,13 +473,13 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
#ifndef CURL_DISABLE_CRYPTO_AUTH
if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) &&
(smtpc->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5";
mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = SMTP_AUTH_DIGESTMD5;
smtpc->authused = SASL_MECH_DIGEST_MD5;
}
else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) &&
(smtpc->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5";
mech = SASL_MECH_STRING_CRAM_MD5;
state1 = SMTP_AUTH_CRAMMD5;
smtpc->authused = SASL_MECH_CRAM_MD5;
}
@@ -484,7 +488,7 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
#ifdef USE_NTLM
if((smtpc->authmechs & SASL_MECH_NTLM) &&
(smtpc->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM";
mech = SASL_MECH_STRING_NTLM;
state1 = SMTP_AUTH_NTLM;
state2 = SMTP_AUTH_NTLM_TYPE2MSG;
smtpc->authused = SASL_MECH_NTLM;
@@ -496,9 +500,22 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
}
else
#endif
if((smtpc->authmechs & SASL_MECH_LOGIN) &&
if(((smtpc->authmechs & SASL_MECH_XOAUTH2) &&
(smtpc->prefmech & SASL_MECH_XOAUTH2) &&
(smtpc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
state1 = SMTP_AUTH_XOAUTH2;
state2 = SMTP_AUTH_FINAL;
smtpc->authused = SASL_MECH_XOAUTH2;
if(data->set.sasl_ir)
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&initresp, &len);
}
else if((smtpc->authmechs & SASL_MECH_LOGIN) &&
(smtpc->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
mech = SASL_MECH_STRING_LOGIN;
state1 = SMTP_AUTH_LOGIN;
state2 = SMTP_AUTH_LOGIN_PASSWD;
smtpc->authused = SASL_MECH_LOGIN;
@@ -509,7 +526,7 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
}
else if((smtpc->authmechs & SASL_MECH_PLAIN) &&
(smtpc->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN";
mech = SASL_MECH_STRING_PLAIN;
state1 = SMTP_AUTH_PLAIN;
state2 = SMTP_AUTH_FINAL;
smtpc->authused = SASL_MECH_PLAIN;
@@ -636,7 +653,7 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
struct SMTP *smtp = data->req.protop;
/* Send the RCPT TO command */
if(smtp->rcpt) {
@@ -1088,6 +1105,43 @@ static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
}
#endif
/* For AUTH XOAUTH2 (without initial response) responses */
static CURLcode smtp_state_auth_xoauth2_resp(struct connectdata *conn,
int smtpcode, smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *xoauth = NULL;
(void)instate; /* no use for this yet */
if(smtpcode != 334) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else {
/* Create the authorisation message */
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&xoauth, &len);
/* Send the message */
if(!result) {
if(xoauth) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth);
if(!result)
state(conn, SMTP_AUTH_FINAL);
}
Curl_safefree(xoauth);
}
}
return result;
}
/* For the final responses to the AUTH sequence */
static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
int smtpcode,
@@ -1115,7 +1169,7 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
struct SMTP *smtp = data->req.protop;
(void)instate; /* no use for this yet */
@@ -1139,7 +1193,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
struct SMTP *smtp = data->req.protop;
(void)instate; /* no use for this yet */
@@ -1296,6 +1350,10 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
break;
#endif
case SMTP_AUTH_XOAUTH2:
result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_AUTH_FINAL:
result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
break;
@@ -1334,11 +1392,13 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone)
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &smtpc->ssldone);
else
result = Curl_pp_statemach(&smtpc->pp, FALSE);
if(result || !smtpc->ssldone)
return result;
}
result = Curl_pp_statemach(&smtpc->pp, FALSE);
*done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE;
return result;
@@ -1361,13 +1421,11 @@ static CURLcode smtp_init(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
struct SMTP *smtp;
if(!smtp) {
smtp = data->state.proto.smtp = calloc(sizeof(struct SMTP), 1);
smtp = data->req.protop = calloc(sizeof(struct SMTP), 1);
if(!smtp)
result = CURLE_OUT_OF_MEMORY;
}
return result;
}
@@ -1397,15 +1455,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
*done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
/* Initialise the SMTP layer */
result = smtp_init(conn);
if(result)
return result;
/* We always support persistent connections in SMTP */
conn->bits.close = FALSE;
@@ -1453,7 +1502,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
struct SMTP *smtp = data->req.protop;
struct pingpong *pp = &conn->proto.smtpc.pp;
const char *eob;
ssize_t len;
@@ -1534,7 +1583,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
if(conn->data->set.opt_no_body) {
/* Requested no body means no transfer */
struct SMTP *smtp = conn->data->state.proto.smtp;
struct SMTP *smtp = conn->data->req.protop;
smtp->transfer = FTPTRANSFER_INFO;
}
@@ -1571,15 +1620,6 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */
/* Since connections can be re-used between SessionHandles, there might be a
connection already existing but on a fresh SessionHandle struct. As such
we make sure we have a good SMTP struct to play with. For new connections
the SMTP struct is allocated and setup in the smtp_connect() function. */
Curl_reset_reqproto(conn);
result = smtp_init(conn);
if(result)
return result;
result = smtp_regular_transfer(conn, done);
return result;
@@ -1622,7 +1662,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn,
/* Call this when the DO phase has completed */
static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected)
{
struct SMTP *smtp = conn->data->state.proto.smtp;
struct SMTP *smtp = conn->data->req.protop;
(void)connected;
@@ -1687,6 +1727,7 @@ static CURLcode smtp_regular_transfer(struct connectdata *conn,
static CURLcode smtp_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
CURLcode result;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel SMTP operations through the proxy, we
@@ -1702,17 +1743,20 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
/* set it up as a HTTP connection instead */
return conn->handler->setup_connection(conn);
/* We explicitly mark this connection as persistent here as we're doing
SMTP over HTTP and thus we accidentally avoid setting this value
otherwise */
conn->bits.close = FALSE;
#else
failf(data, "SMTP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
/* Initialise the SMTP layer */
result = smtp_init(conn);
if(result)
return result;
data->state.path++; /* don't include the initial slash */
return CURLE_OK;
@@ -1742,18 +1786,20 @@ static CURLcode smtp_parse_url_options(struct connectdata *conn)
if(strequal(value, "*"))
smtpc->prefmech = SASL_AUTH_ANY;
else if(strequal(value, "LOGIN"))
else if(strequal(value, SASL_MECH_STRING_LOGIN))
smtpc->prefmech = SASL_MECH_LOGIN;
else if(strequal(value, "PLAIN"))
else if(strequal(value, SASL_MECH_STRING_PLAIN))
smtpc->prefmech = SASL_MECH_PLAIN;
else if(strequal(value, "CRAM-MD5"))
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5))
smtpc->prefmech = SASL_MECH_CRAM_MD5;
else if(strequal(value, "DIGEST-MD5"))
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5))
smtpc->prefmech = SASL_MECH_DIGEST_MD5;
else if(strequal(value, "GSSAPI"))
else if(strequal(value, SASL_MECH_STRING_GSSAPI))
smtpc->prefmech = SASL_MECH_GSSAPI;
else if(strequal(value, "NTLM"))
else if(strequal(value, SASL_MECH_STRING_NTLM))
smtpc->prefmech = SASL_MECH_NTLM;
else if(strequal(value, SASL_MECH_STRING_XOAUTH2))
smtpc->prefmech = SASL_MECH_XOAUTH2;
else
smtpc->prefmech = SASL_AUTH_NONE;
}
@@ -1801,7 +1847,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
ssize_t i;
ssize_t si;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
struct SMTP *smtp = data->req.protop;
/* Do we need to allocate the scatch buffer? */
if(!data->state.scratch) {

View File

@@ -44,6 +44,7 @@ typedef enum {
SMTP_AUTH_DIGESTMD5_RESP,
SMTP_AUTH_NTLM,
SMTP_AUTH_NTLM_TYPE2MSG,
SMTP_AUTH_XOAUTH2,
SMTP_AUTH_FINAL,
SMTP_MAIL, /* MAIL FROM */
SMTP_RCPT, /* RCPT TO */

View File

@@ -149,13 +149,15 @@ static int ssh_perform_getsock(const struct connectdata *conn,
number of sockets */
int numsocks);
static CURLcode ssh_setup_connection(struct connectdata *conn);
/*
* SCP protocol handler.
*/
const struct Curl_handler Curl_handler_scp = {
"SCP", /* scheme */
ZERO_NULL, /* setup_connection */
ssh_setup_connection, /* setup_connection */
ssh_do, /* do_it */
scp_done, /* done */
ZERO_NULL, /* do_more */
@@ -181,7 +183,7 @@ const struct Curl_handler Curl_handler_scp = {
const struct Curl_handler Curl_handler_sftp = {
"SFTP", /* scheme */
ZERO_NULL, /* setup_connection */
ssh_setup_connection, /* setup_connection */
ssh_do, /* do_it */
sftp_done, /* done */
ZERO_NULL, /* do_more */
@@ -200,7 +202,6 @@ const struct Curl_handler Curl_handler_sftp = {
| PROTOPT_NOURLQUERY /* flags */
};
static void
kbd_callback(const char *name, int name_len, const char *instruction,
int instruction_len, int num_prompts,
@@ -687,7 +688,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SSHPROTO *sftp_scp = data->state.proto.ssh;
struct SSHPROTO *sftp_scp = data->req.protop;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
char *new_readdir_line;
@@ -2287,6 +2288,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = result;
}
else {
/* store this original bitmask setup to use later on if we can't
figure out a "real" bitmask */
sshc->orig_waitfor = data->req.keepon;
/* we want to use the _sending_ function even when the socket turns
out readable as the underlying libssh2 scp send function will deal
with both accordingly */
@@ -2603,9 +2608,7 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block)
{
struct ssh_conn *sshc = &conn->proto.sshc;
int dir;
if(!block)
conn->waitfor = 0;
else if((dir = libssh2_session_block_directions(sshc->ssh_session))) {
if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
/* translate the libssh2 define bits into our own bit defines */
conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
@@ -2689,25 +2692,14 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
/*
* SSH setup and connection
*/
static CURLcode ssh_init(struct connectdata *conn)
static CURLcode ssh_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct SSHPROTO *ssh;
struct ssh_conn *sshc = &conn->proto.sshc;
sshc->actualcode = CURLE_OK; /* reset error code */
sshc->secondCreateDirs =0; /* reset the create dir attempt state
variable */
if(data->state.proto.ssh)
return CURLE_OK;
ssh = calloc(1, sizeof(struct SSHPROTO));
conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
if(!ssh)
return CURLE_OUT_OF_MEMORY;
data->state.proto.ssh = ssh;
return CURLE_OK;
}
@@ -2731,14 +2723,6 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
function to make the re-use checks properly be able to check this bit. */
conn->bits.close = FALSE;
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
result = ssh_init(conn);
if(result)
return result;
if(conn->handler->protocol & CURLPROTO_SCP) {
conn->recv[FIRSTSOCKET] = scp_recv;
conn->send[FIRSTSOCKET] = scp_send;
@@ -2856,23 +2840,16 @@ static CURLcode ssh_do(struct connectdata *conn, bool *done)
CURLcode res;
bool connected = 0;
struct SessionHandle *data = conn->data;
struct ssh_conn *sshc = &conn->proto.sshc;
*done = FALSE; /* default to false */
/*
Since connections can be re-used between SessionHandles, this might be a
connection already existing but on a fresh SessionHandle struct so we must
make sure we have a good 'struct SSHPROTO' to play with. For new
connections, the struct SSHPROTO is allocated and setup in the
ssh_connect() function.
*/
Curl_reset_reqproto(conn);
res = ssh_init(conn);
if(res)
return res;
data->req.size = -1; /* make sure this is unknown at this point */
sshc->actualcode = CURLE_OK; /* reset error code */
sshc->secondCreateDirs =0; /* reset the create dir attempt state
variable */
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0);
@@ -2895,7 +2872,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
struct ssh_conn *ssh = &conn->proto.sshc;
(void) dead_connection;
Curl_safefree(conn->data->state.proto.ssh);
Curl_safefree(conn->data->req.protop);
if(ssh->ssh_session) {
/* only if there's a session still around to use! */
@@ -2913,7 +2890,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
{
CURLcode result = CURLE_OK;
struct SSHPROTO *sftp_scp = conn->data->state.proto.ssh;
struct SSHPROTO *sftp_scp = conn->data->req.protop;
if(status == CURLE_OK) {
/* run the state-machine
@@ -3060,7 +3037,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
Curl_safefree(conn->data->state.proto.ssh);
Curl_safefree(conn->data->req.protop);
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */

View File

@@ -294,6 +294,49 @@ static int do_file_type(const char *type)
return -1;
}
#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_LOAD_FOUR_ARGS)
/*
* Supply default password to the engine user interface conversation.
* The password is passed by OpenSSL engine from ENGINE_load_private_key()
* last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
*/
static int ssl_ui_reader(UI *ui, UI_STRING *uis)
{
const char *password;
switch(UI_get_string_type(uis)) {
case UIT_PROMPT:
case UIT_VERIFY:
password = (const char*)UI_get0_user_data(ui);
if(NULL != password &&
UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
UI_set_result(ui, uis, password);
return 1;
}
default:
break;
}
return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
}
/*
* Suppress interactive request for a default password if available.
*/
static int ssl_ui_writer(UI *ui, UI_STRING *uis)
{
switch(UI_get_string_type(uis)) {
case UIT_PROMPT:
case UIT_VERIFY:
if(NULL != UI_get0_user_data(ui) &&
UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
return 1;
}
default:
break;
}
return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
}
#endif
static
int cert_stuff(struct connectdata *conn,
SSL_CTX* ctx,
@@ -527,7 +570,16 @@ int cert_stuff(struct connectdata *conn,
EVP_PKEY *priv_key = NULL;
if(data->state.engine) {
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
UI_METHOD *ui_method = UI_OpenSSL();
UI_METHOD *ui_method =
UI_create_method((char *)"cURL user interface");
if(NULL == ui_method) {
failf(data, "unable do create OpenSSL user-interface method");
return 0;
}
UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
UI_method_set_reader(ui_method, ssl_ui_reader);
UI_method_set_writer(ui_method, ssl_ui_writer);
#endif
/* the typecast below was added to please mingw32 */
priv_key = (EVP_PKEY *)
@@ -536,6 +588,9 @@ int cert_stuff(struct connectdata *conn,
ui_method,
#endif
data->set.str[STRING_KEY_PASSWD]);
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
UI_destroy_method(ui_method);
#endif
if(!priv_key) {
failf(data, "failed to load private key from crypto engine");
return 0;
@@ -1137,6 +1192,8 @@ static CURLcode verifyhost(struct connectdata *conn,
/* an alternative name field existed, but didn't match and then
we MUST fail */
infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
failf(data, "SSL: no alternative certificate subject name matches "
"target host name '%s'", conn->host.dispname);
res = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -1755,7 +1812,7 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
*/
if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
conn->host.name, conn->port);
conn->host.name, conn->remote_port);
return rc;
}
/* Could be a CERT problem */
@@ -2296,7 +2353,7 @@ ossl_connect_step3(struct connectdata *conn,
* operations.
*/
if(!data->set.ssl.verifypeer)
if(!data->set.ssl.verifypeer && !data->set.ssl.verifyhost)
(void)servercert(conn, connssl, FALSE);
else
retcode = servercert(conn, connssl, TRUE);

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2004 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2004 - 2013, 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
@@ -361,6 +361,9 @@ curl_multi_strerror(CURLMcode error)
case CURLM_UNKNOWN_OPTION:
return "Unknown option";
case CURLM_ADDED_ALREADY:
return "The easy handle is already added to a multi handle";
case CURLM_LAST:
break;
}

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -247,7 +247,7 @@ CURLcode init_telnet(struct connectdata *conn)
if(!tn)
return CURLE_OUT_OF_MEMORY;
conn->data->state.proto.telnet = (void *)tn; /* make us known */
conn->data->req.protop = tn; /* make us known */
tn->telrcv_state = CURL_TS_DATA;
@@ -292,7 +292,7 @@ CURLcode init_telnet(struct connectdata *conn)
static void negotiate(struct connectdata *conn)
{
int i;
struct TELNET *tn = (struct TELNET *) conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
for(i = 0;i < CURL_NTELOPTS;i++) {
if(i==CURL_TELOPT_ECHO)
@@ -366,7 +366,7 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
static
void set_remote_option(struct connectdata *conn, int option, int newstate)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
if(newstate == CURL_YES) {
switch(tn->him[option]) {
case CURL_NO:
@@ -440,7 +440,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate)
static
void rec_will(struct connectdata *conn, int option)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
switch(tn->him[option]) {
case CURL_NO:
if(tn->him_preferred[option] == CURL_YES) {
@@ -488,7 +488,7 @@ void rec_will(struct connectdata *conn, int option)
static
void rec_wont(struct connectdata *conn, int option)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
switch(tn->him[option]) {
case CURL_NO:
/* Already disabled */
@@ -530,7 +530,7 @@ void rec_wont(struct connectdata *conn, int option)
static void
set_local_option(struct connectdata *conn, int option, int newstate)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
@@ -604,7 +604,7 @@ set_local_option(struct connectdata *conn, int option, int newstate)
static
void rec_do(struct connectdata *conn, int option)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
switch(tn->us[option]) {
case CURL_NO:
if(tn->us_preferred[option] == CURL_YES) {
@@ -664,7 +664,7 @@ void rec_do(struct connectdata *conn, int option)
static
void rec_dont(struct connectdata *conn, int option)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
@@ -825,7 +825,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
char option_keyword[128];
char option_arg[256];
struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
CURLcode result = CURLE_OK;
int binary_option;
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
char varname[128];
char varval[128];
struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)data->req.protop;
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
switch (CURL_SB_GET(tn)) {
@@ -1009,7 +1009,7 @@ static void sendsuboption(struct connectdata *conn, int option)
unsigned char*uc1, *uc2;
struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)data->req.protop;
switch (option) {
case CURL_TELOPT_NAWS:
@@ -1067,7 +1067,7 @@ CURLcode telrcv(struct connectdata *conn,
int in = 0;
int startwrite=-1;
struct SessionHandle *data = conn->data;
struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)data->req.protop;
#define startskipping() \
if(startwrite >= 0) { \
@@ -1264,7 +1264,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
static CURLcode telnet_done(struct connectdata *conn,
CURLcode status, bool premature)
{
struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
(void)status; /* unused */
(void)premature; /* not used */
@@ -1274,7 +1274,7 @@ static CURLcode telnet_done(struct connectdata *conn,
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
Curl_safefree(conn->data->state.proto.telnet);
Curl_safefree(conn->data->req.protop);
return CURLE_OK;
}
@@ -1318,7 +1318,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
if(code)
return code;
tn = (struct TELNET *)data->state.proto.telnet;
tn = (struct TELNET *)data->req.protop;
code = check_telnet_options(conn);
if(code)

View File

@@ -56,6 +56,7 @@
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "speedcheck.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -947,10 +948,6 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
blksize = TFTP_BLKSIZE_DEFAULT;
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
if(!state)
return CURLE_OUT_OF_MEMORY;
@@ -1259,6 +1256,15 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
else {
/* The multi code doesn't have this logic for the DOING state so we
provide it for TFTP since it may do the entire transfer in this
state. */
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
else
result = Curl_speedcheck(conn->data, Curl_tvnow());
}
return result;
}
@@ -1307,14 +1313,6 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
*done = FALSE;
/*
Since connections can be re-used between SessionHandles, this might be a
connection already existing but on a fresh SessionHandle struct so we must
make sure we have a good 'struct TFTP' to play with. For new connections,
the struct TFTP is allocated and setup in the tftp_connect() function.
*/
Curl_reset_reqproto(conn);
if(!conn->proto.tftpc) {
code = tftp_connect(conn, done);
if(code)

View File

@@ -101,8 +101,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
#ifdef CURL_DOES_CONVERSIONS
bool sending_http_headers = FALSE;
if((conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) &&
(data->state.proto.http->sending == HTTPSEND_REQUEST)) {
if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) {
const struct HTTP *http = data->req.protop;
if(http->sending == HTTPSEND_REQUEST)
/* We're sending the HTTP request headers, not the data.
Remember that so we don't re-translate them into garbage. */
sending_http_headers = TRUE;
@@ -540,6 +542,10 @@ static CURLcode readwrite_data(struct SessionHandle *data,
if(!Curl_meets_timecondition(data, k->timeofdoc)) {
*done = TRUE;
/* We're simulating a http 304 from server so we return
what should have been returned from the server */
data->info.httpcode = 304;
infof(data, "Simulate a HTTP 304 response!\n");
/* we abort the transfer before it is completed == we ruin the
re-use ability. Close the connection */
conn->bits.close = TRUE;
@@ -810,9 +816,10 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
/* HTTP pollution, this should be written nicer to become more
protocol agnostic. */
int fillcount;
struct HTTP *http = data->req.protop;
if((k->exp100 == EXP100_SENDING_REQUEST) &&
(data->state.proto.http->sending == HTTPSEND_BODY)) {
(http->sending == HTTPSEND_BODY)) {
/* If this call is to send body data, we must take some action:
We have sent off the full HTTP 1.1 request, and we shall now
go into the Expect: 100 state and await such a header */
@@ -827,7 +834,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
}
if(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP)) {
if(data->state.proto.http->sending == HTTPSEND_REQUEST)
if(http->sending == HTTPSEND_REQUEST)
/* We're sending the HTTP request headers, not the data.
Remember that so we don't change the line endings. */
sending_http_headers = TRUE;
@@ -1870,10 +1877,12 @@ CURLcode Curl_retry_request(struct connectdata *conn,
transferred! */
if((conn->handler->protocol&CURLPROTO_HTTP) &&
data->state.proto.http->writebytecount)
if(conn->handler->protocol&CURLPROTO_HTTP) {
struct HTTP *http = data->req.protop;
if(http->writebytecount)
return Curl_readrewind(conn);
}
}
return CURLE_OK;
}
@@ -1930,6 +1939,7 @@ Curl_setup_transfer(
k->keepon |= KEEP_RECV;
if(conn->writesockfd != CURL_SOCKET_BAD) {
struct HTTP *http = data->req.protop;
/* HTTP 1.1 magic:
Even if we require a 100-return code before uploading data, we might
@@ -1940,13 +1950,16 @@ Curl_setup_transfer(
state info where we wait for the 100-return code
*/
if((data->state.expect100header) &&
(data->state.proto.http->sending == HTTPSEND_BODY)) {
(conn->handler->protocol&CURLPROTO_HTTP) &&
(http->sending == HTTPSEND_BODY)) {
/* wait with write until we either got 100-continue or a timeout */
k->exp100 = EXP100_AWAITING_CONTINUE;
k->start100 = Curl_tvnow();
/* set a timeout for the multi interface */
Curl_expire(data, CURL_TIMEOUT_EXPECT_100);
/* Set a timeout for the multi interface. Add the inaccuracy margin so
that we don't fire slightly too early and get denied to run. */
Curl_expire(data, CURL_TIMEOUT_EXPECT_100 +
MULTI_TIMEOUT_INACCURACY / 1000);
}
else {
if(data->state.expect100header)

324
lib/url.c
View File

@@ -144,7 +144,8 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
static CURLcode do_init(struct connectdata *conn);
static CURLcode parse_url_login(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd, char *options);
char **userptr, char **passwdptr,
char **optionsptr);
static CURLcode parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
@@ -417,7 +418,8 @@ CURLcode Curl_close(struct SessionHandle *data)
Curl_safefree(data->state.pathbuffer);
data->state.path = NULL;
Curl_safefree(data->state.proto.generic);
/* freed here just in case DONE wasn't called */
Curl_free_request_state(data);
/* Close down all open SSL info and sessions */
Curl_ssl_close_all(data);
@@ -611,7 +613,6 @@ CURLcode Curl_open(struct SessionHandle **curl)
res = CURLE_OUT_OF_MEMORY;
}
else {
Curl_easy_initHandleData(data);
res = Curl_init_userdefined(&data->set);
data->state.headersize=HEADERSIZE;
@@ -1202,7 +1203,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* This sets a requested HTTP version to be used. The value is one of
* the listed enums in curl/curl.h.
*/
data->set.httpversion = va_arg(param, long);
arg = va_arg(param, long);
#ifndef USE_NGHTTP2
if(arg == CURL_HTTP_VERSION_2_0)
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
data->set.httpversion = arg;
break;
case CURLOPT_HTTPAUTH:
@@ -1568,6 +1574,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
result = setstropt(&data->set.str[STRING_PASSWORD],
va_arg(param, char *));
break;
case CURLOPT_XOAUTH2_BEARER:
/*
* XOAUTH2 bearer token to use in the operation
*/
result = setstropt(&data->set.str[STRING_BEARER],
va_arg(param, char *));
break;
case CURLOPT_POSTQUOTE:
/*
* List of RAW FTP commands to use after a transfer
@@ -2442,6 +2455,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
case CURLOPT_DNS_SERVERS:
result = Curl_set_dns_servers(data, va_arg(param, char *));
break;
case CURLOPT_DNS_INTERFACE:
result = Curl_set_dns_interface(data, va_arg(param, char *));
break;
case CURLOPT_DNS_LOCAL_IP4:
result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
break;
case CURLOPT_DNS_LOCAL_IP6:
result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
break;
case CURLOPT_TCP_KEEPALIVE:
data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE;
@@ -2487,6 +2509,7 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->xoauth2_bearer);
Curl_safefree(conn->options);
Curl_safefree(conn->proxyuser);
Curl_safefree(conn->proxypasswd);
@@ -3606,7 +3629,7 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
if(!conn->send_pipe || !conn->recv_pipe)
goto error;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CLEAR;
#endif
@@ -3687,7 +3710,8 @@ static CURLcode findprotocol(struct SessionHandle *data,
static CURLcode parseurlandfillconn(struct SessionHandle *data,
struct connectdata *conn,
bool *prot_missing,
char *user, char *passwd, char *options)
char **userp, char **passwdp,
char **optionsp)
{
char *at;
char *fragment;
@@ -3931,7 +3955,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
* Parse the login details from the URL and strip them out of
* the host name
*/
result = parse_url_login(data, conn, user, passwd, options);
result = parse_url_login(data, conn, userp, passwdp, optionsp);
if(result != CURLE_OK)
return result;
@@ -4016,18 +4040,31 @@ static CURLcode setup_range(struct SessionHandle *data)
}
/***************************************************************
* Setup connection internals specific to the requested protocol.
/*
* setup_connection_internals() -
*
* Setup connection internals specific to the requested protocol in the
* SessionHandle. This is inited and setup before the connection is made but
* is about the particular protocol that is to be used.
*
* This MUST get called after proxy magic has been figured out.
***************************************************************/
*/
static CURLcode setup_connection_internals(struct connectdata *conn)
{
const struct Curl_handler * p;
CURLcode result;
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
/* in some case in the multi state-machine, we go back to the CONNECT state
and then a second (or third or...) call to this function will be made
without doing a DISCONNECT or DONE in between (since the connection is
yet in place) and therefore this function needs to first make sure
there's no lingering previous data allocated. */
Curl_free_request_state(conn->data);
/* Scan protocol handler table. */
memset(&conn->data->req, 0, sizeof(struct SingleRequest));
conn->data->req.maxdownload = -1;
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
/* Perform setup complement if some. */
p = conn->handler;
@@ -4045,11 +4082,26 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
/* we check for -1 here since if proxy was detected already, this
was very likely already set to the proxy port */
conn->port = p->defport;
/* only if remote_port was not already parsed off the URL we use the
default port number */
if(!conn->remote_port)
conn->remote_port = (unsigned short)conn->given->defport;
return CURLE_OK;
}
/*
* Curl_free_request_state() should free temp data that was allocated in the
* SessionHandle for this single request.
*/
void Curl_free_request_state(struct SessionHandle *data)
{
Curl_safefree(data->req.protop);
}
#ifndef CURL_DISABLE_PROXY
/****************************************************************
* Checks if the host is in the noproxy list. returns true if it matches
@@ -4411,7 +4463,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
*/
static CURLcode parse_url_login(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd, char *options)
char **user, char **passwd, char **options)
{
CURLcode result = CURLE_OK;
char *userp = NULL;
@@ -4428,16 +4480,16 @@ static CURLcode parse_url_login(struct SessionHandle *data,
char *ptr = strchr(conn->host.name, '@');
char *login = conn->host.name;
user[0] = 0; /* to make everything well-defined */
passwd[0] = 0;
options[0] = 0;
DEBUGASSERT(!**user);
DEBUGASSERT(!**passwd);
DEBUGASSERT(!**options);
if(!ptr)
goto out;
/* We will now try to extract the
* possible login information in a string like:
* ftp://user:password@ftp.my.site:8021/README */
if(ptr) {
/* There's login information to the left of the @ */
conn->host.name = ++ptr;
/* So the hostname is sane. Only bother interpreting the
@@ -4446,11 +4498,15 @@ static CURLcode parse_url_login(struct SessionHandle *data,
* set user/passwd, but doing that first adds more cases here :-(
*/
if(data->set.use_netrc != CURL_NETRC_REQUIRED) {
if(data->set.use_netrc == CURL_NETRC_REQUIRED)
goto out;
/* We could use the login information in the URL so extract it */
result = parse_login_details(login, ptr - login - 1,
&userp, &passwdp, &optionsp);
if(!result) {
if(result != CURLE_OK)
goto out;
if(userp) {
char *newname;
@@ -4461,56 +4517,44 @@ static CURLcode parse_url_login(struct SessionHandle *data,
/* Decode the user */
newname = curl_easy_unescape(data, userp, 0, NULL);
if(!newname) {
Curl_safefree(userp);
Curl_safefree(passwdp);
Curl_safefree(optionsp);
return CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
goto out;
}
if(strlen(newname) < MAX_CURL_USER_LENGTH)
strcpy(user, newname);
free(newname);
free(*user);
*user = newname;
}
if(passwdp) {
/* We have a password in the URL so decode it */
char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
if(!newpasswd) {
Curl_safefree(userp);
Curl_safefree(passwdp);
Curl_safefree(optionsp);
return CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
goto out;
}
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
strcpy(passwd, newpasswd);
free(newpasswd);
free(*passwd);
*passwd = newpasswd;
}
if(optionsp) {
/* We have an options list in the URL so decode it */
char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
if(!newoptions) {
Curl_safefree(userp);
Curl_safefree(passwdp);
Curl_safefree(optionsp);
return CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
goto out;
}
if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
strcpy(options, newoptions);
free(*options);
*options = newoptions;
}
free(newoptions);
}
}
out:
Curl_safefree(userp);
Curl_safefree(passwdp);
Curl_safefree(optionsp);
}
}
return result;
}
@@ -4765,29 +4809,35 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
* Override the login details from the URL with that in the CURLOPT_USERPWD
* option or a .netrc file, if applicable.
*/
static void override_login(struct SessionHandle *data,
static CURLcode override_login(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd, char *options)
char **userp, char **passwdp, char **optionsp)
{
if(data->set.str[STRING_USERNAME]) {
strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH);
user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */
free(*userp);
*userp = strdup(data->set.str[STRING_USERNAME]);
if(!*userp)
return CURLE_OUT_OF_MEMORY;
}
if(data->set.str[STRING_PASSWORD]) {
strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH);
passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */
free(*passwdp);
*passwdp = strdup(data->set.str[STRING_PASSWORD]);
if(!*passwdp)
return CURLE_OUT_OF_MEMORY;
}
if(data->set.str[STRING_OPTIONS]) {
strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH);
options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */
free(*optionsp);
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
if(!*optionsp)
return CURLE_OUT_OF_MEMORY;
}
conn->bits.netrc = FALSE;
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
if(Curl_parsenetrc(conn->host.name,
user, passwd,
userp, passwdp,
data->set.str[STRING_NETRC_FILE])) {
infof(data, "Couldn't find host %s in the "
DOT_CHAR "netrc file; using defaults\n",
@@ -4802,6 +4852,8 @@ static void override_login(struct SessionHandle *data,
conn->bits.user_passwd = TRUE; /* enable user+password */
}
}
return CURLE_OK;
}
/*
@@ -5018,9 +5070,9 @@ static CURLcode create_conn(struct SessionHandle *data,
struct connectdata *conn;
struct connectdata *conn_temp = NULL;
size_t urllen;
char user[MAX_CURL_USER_LENGTH];
char passwd[MAX_CURL_PASSWORD_LENGTH];
char options[MAX_CURL_OPTIONS_LENGTH];
char *user = NULL;
char *passwd = NULL;
char *options = NULL;
bool reuse;
char *proxy = NULL;
bool prot_missing = FALSE;
@@ -5035,8 +5087,10 @@ static CURLcode create_conn(struct SessionHandle *data,
* Check input data
*************************************************************/
if(!data->change.url)
return CURLE_URL_MALFORMAT;
if(!data->change.url) {
result = CURLE_URL_MALFORMAT;
goto out;
}
/* First, split up the current URL in parts so that we can use the
parts for checking against the already present connections. In order
@@ -5044,8 +5098,10 @@ static CURLcode create_conn(struct SessionHandle *data,
connection data struct and fill in for comparison purposes. */
conn = allocate_conn(data);
if(!conn)
return CURLE_OUT_OF_MEMORY;
if(!conn) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
/* We must set the return variable as soon as possible, so that our
parent can cleanup any possible allocs we may have done before
@@ -5075,24 +5131,35 @@ static CURLcode create_conn(struct SessionHandle *data,
data->state.path = NULL;
data->state.pathbuffer = malloc(urllen+2);
if(NULL == data->state.pathbuffer)
return CURLE_OUT_OF_MEMORY; /* really bad error */
if(NULL == data->state.pathbuffer) {
result = CURLE_OUT_OF_MEMORY; /* really bad error */
goto out;
}
data->state.path = data->state.pathbuffer;
conn->host.rawalloc = malloc(urllen+2);
if(NULL == conn->host.rawalloc) {
Curl_safefree(data->state.pathbuffer);
data->state.path = NULL;
return CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
goto out;
}
conn->host.name = conn->host.rawalloc;
conn->host.name[0] = 0;
result = parseurlandfillconn(data, conn, &prot_missing, user, passwd,
options);
user = strdup("");
passwd = strdup("");
options = strdup("");
if(!user || !passwd || !options) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
&options);
if(result != CURLE_OK)
return result;
goto out;
/*************************************************************
* No protocol part in URL was used, add it!
@@ -5106,8 +5173,8 @@ static CURLcode create_conn(struct SessionHandle *data,
reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
if(!reurl) {
Curl_safefree(proxy);
return CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
goto out;
}
if(data->change.url_alloc) {
@@ -5137,6 +5204,13 @@ static CURLcode create_conn(struct SessionHandle *data,
}
}
if(data->set.str[STRING_BEARER]) {
conn->xoauth2_bearer = strdup(data->set.str[STRING_BEARER]);
if(!conn->xoauth2_bearer) {
return CURLE_OUT_OF_MEMORY;
}
}
#ifndef CURL_DISABLE_PROXY
/*************************************************************
* Extract the user and password from the authentication string
@@ -5144,7 +5218,7 @@ static CURLcode create_conn(struct SessionHandle *data,
if(conn->bits.proxy_user_passwd) {
result = parse_proxy_auth(data, conn);
if(result != CURLE_OK)
return result;
goto out;
}
/*************************************************************
@@ -5155,7 +5229,8 @@ static CURLcode create_conn(struct SessionHandle *data,
/* if global proxy is set, this is it */
if(NULL == proxy) {
failf(data, "memory shortage");
return CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
goto out;
}
}
@@ -5183,16 +5258,17 @@ static CURLcode create_conn(struct SessionHandle *data,
if(proxy) {
result = parse_proxy(data, conn, proxy);
free(proxy); /* parse_proxy copies the proxy string */
Curl_safefree(proxy); /* parse_proxy copies the proxy string */
if(result)
return result;
goto out;
if((conn->proxytype == CURLPROXY_HTTP) ||
(conn->proxytype == CURLPROXY_HTTP_1_0)) {
#ifdef CURL_DISABLE_HTTP
/* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
return CURLE_UNSUPPORTED_PROTOCOL;
result = CURLE_UNSUPPORTED_PROTOCOL;
goto out;
#else
/* force this connection's protocol to become HTTP if not already
compatible - if it isn't tunneling through */
@@ -5217,15 +5293,36 @@ static CURLcode create_conn(struct SessionHandle *data,
#endif /* CURL_DISABLE_PROXY */
/*************************************************************
* If the protocol is using SSL and HTTP proxy is used, we set
* the tunnel_proxy bit.
*************************************************************/
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
conn->bits.tunnel_proxy = TRUE;
/*************************************************************
* Figure out the remote port number and fix it in the URL
*************************************************************/
result = parse_remote_port(data, conn);
if(result != CURLE_OK)
goto out;
/* Check for overridden login details and set them accordingly so they
they are known when protocol->setup_connection is called! */
result = override_login(data, conn, &user, &passwd, &options);
if(result != CURLE_OK)
goto out;
result = set_login(conn, user, passwd, options);
if(result != CURLE_OK)
goto out;
/*************************************************************
* Setup internals depending on protocol. Needs to be done after
* we figured out what/if proxy to use.
*************************************************************/
result = setup_connection_internals(conn);
if(result != CURLE_OK) {
Curl_safefree(proxy);
return result;
}
if(result != CURLE_OK)
goto out;
conn->recv[FIRSTSOCKET] = Curl_recv_plain;
conn->send[FIRSTSOCKET] = Curl_send_plain;
@@ -5258,7 +5355,7 @@ static CURLcode create_conn(struct SessionHandle *data,
DEBUGASSERT(conn->handler->done);
/* we ignore the return code for the protocol-specific DONE */
(void)conn->handler->done(conn, result, FALSE);
return result;
goto out;
}
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
@@ -5266,32 +5363,12 @@ static CURLcode create_conn(struct SessionHandle *data,
}
/* since we skip do_init() */
Curl_speedinit(data);
do_init(conn);
return result;
goto out;
}
#endif
/*************************************************************
* If the protocol is using SSL and HTTP proxy is used, we set
* the tunnel_proxy bit.
*************************************************************/
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
conn->bits.tunnel_proxy = TRUE;
/*************************************************************
* Figure out the remote port number and fix it in the URL
*************************************************************/
result = parse_remote_port(data, conn);
if(result != CURLE_OK)
return result;
/* Check for overridden login details and set them accordingly */
override_login(data, conn, user, passwd, options);
result = set_login(conn, user, passwd, options);
if(result != CURLE_OK)
return result;
/* Get a cloned copy of the SSL config situation stored in the
connection struct. But to get this going nicely, we must first make
sure that the strings in the master copy are pointing to the correct
@@ -5313,8 +5390,10 @@ static CURLcode create_conn(struct SessionHandle *data,
data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
#endif
if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
return CURLE_OUT_OF_MEMORY;
if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
/*************************************************************
* Check the current list of connections to see if we can
@@ -5417,7 +5496,8 @@ static CURLcode create_conn(struct SessionHandle *data,
conn_free(conn);
*in_connect = NULL;
return CURLE_NO_CONNECTION_AVAILABLE;
result = CURLE_NO_CONNECTION_AVAILABLE;
goto out;
}
else {
/*
@@ -5439,7 +5519,7 @@ static CURLcode create_conn(struct SessionHandle *data,
*/
result = setup_range(data);
if(result)
return result;
goto out;
/* Continue connectdata initialization here. */
@@ -5457,6 +5537,12 @@ static CURLcode create_conn(struct SessionHandle *data,
*************************************************************/
result = resolve_server(data, conn, async);
out:
Curl_safefree(options);
Curl_safefree(passwd);
Curl_safefree(user);
Curl_safefree(proxy);
return result;
}
@@ -5666,12 +5752,18 @@ CURLcode Curl_done(struct connectdata **connp,
conn->dns_entry = NULL;
}
if(status == CURLE_ABORTED_BY_CALLBACK)
switch(status) {
case CURLE_ABORTED_BY_CALLBACK:
case CURLE_READ_ERROR:
case CURLE_WRITE_ERROR:
/* When we're aborted due to a callback return code it basically have to
be counted as premature as there is trouble ahead if we don't. We have
many callbacks and protocols work differently, we could potentially do
this more fine-grained in the future. */
premature = TRUE;
default:
break;
}
/* this calls the protocol-specific function pointer previously set */
if(conn->handler->done)
@@ -5728,6 +5820,7 @@ CURLcode Curl_done(struct connectdata **connp,
this was either closed or handed over to the connection
cache here, and therefore cannot be used from this point on
*/
Curl_free_request_state(data);
return result;
}
@@ -5760,9 +5853,6 @@ static CURLcode do_init(struct connectdata *conn)
HTTP. */
data->set.httpreq = HTTPREQ_GET;
/* NB: the content encoding software depends on this initialization */
Curl_easy_initHandleData(data);
k->start = Curl_tvnow(); /* start time */
k->now = k->start; /* current time is now */
k->header = TRUE; /* assume header */
@@ -5861,13 +5951,3 @@ CURLcode Curl_do_more(struct connectdata *conn, int *complete)
return result;
}
/* Called on connect, and if there's already a protocol-specific struct
allocated for a different connection, this frees it that it can be setup
properly later on. */
void Curl_reset_reqproto(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
Curl_safefree(data->state.proto.generic);
data->state.proto.generic = NULL;
}

View File

@@ -45,6 +45,7 @@ CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
CURLcode Curl_setup_conn(struct connectdata *conn,
bool *protocol_done);
void Curl_free_request_state(struct SessionHandle *data);
int Curl_protocol_getsock(struct connectdata *conn,
curl_socket_t *socks,
@@ -65,11 +66,6 @@ void Curl_getoff_all_pipelines(struct SessionHandle *data,
void Curl_close_connections(struct SessionHandle *data);
/* Called on connect, and if there's already a protocol-specific struct
allocated for a different connection, this frees it that it can be setup
properly later on. */
void Curl_reset_reqproto(struct connectdata *conn);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
service */

View File

@@ -222,9 +222,9 @@
#define CURLMIN(x,y) ((x)<(y)?(x):(y))
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
/* Types needed for krb4/5-ftp connections */
struct krb4buffer {
#ifdef HAVE_GSSAPI
/* Types needed for krb5-ftp connections */
struct krb5buffer {
void *data;
size_t size;
size_t index;
@@ -692,6 +692,9 @@ struct SingleRequest {
bool forbidchunk; /* used only to explicitly forbid chunk-upload for
specific upload buffers. See readmoredata() in
http.c for details. */
void *protop; /* Allocated protocol-specific data. Each protocol
handler makes sure this points to data it needs. */
};
/*
@@ -873,6 +876,8 @@ struct connectdata {
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
char *xoauth2_bearer; /* bearer token for xoauth2, allocated */
char *proxyuser; /* proxy user name string, allocated */
char *proxypasswd; /* proxy password string, allocated */
curl_proxytype proxytype; /* what kind of proxy that is in use */
@@ -931,12 +936,12 @@ struct connectdata {
} allocptr;
int sec_complete; /* if kerberos is enabled for this connection */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#ifdef HAVE_GSSAPI
enum protection_level command_prot;
enum protection_level data_prot;
enum protection_level request_data_prot;
size_t buffer_size;
struct krb4buffer in_buffer;
struct krb5buffer in_buffer;
void *app_data;
const struct Curl_sec_client_mech *mech;
struct sockaddr_in local_addr;
@@ -996,13 +1001,14 @@ struct connectdata {
union {
struct ftp_conn ftpc;
struct http_conn httpc;
struct ssh_conn sshc;
struct tftp_state_data *tftpc;
struct imap_conn imapc;
struct pop3_conn pop3c;
struct smtp_conn smtpc;
struct rtsp_conn rtspc;
void *generic;
void *generic; /* RTMP and LDAP use this */
} proto;
int cselect_bits; /* bitmask of socket events */
@@ -1149,7 +1155,6 @@ typedef enum {
* Session-data MUST be put in the connectdata struct and here. */
#define MAX_CURL_USER_LENGTH 256
#define MAX_CURL_PASSWORD_LENGTH 256
#define MAX_CURL_OPTIONS_LENGTH 256
struct auth {
unsigned long want; /* Bitmask set to the authentication methods wanted by
@@ -1274,28 +1279,6 @@ struct UrlState {
long rtsp_next_server_CSeq; /* the session's next server CSeq */
long rtsp_CSeq_recv; /* most recent CSeq received */
/* Protocol specific data.
*
*************************************************************************
* Note that this data will be REMOVED after each request, so anything that
* should be kept/stored on a per-connection basis and thus live for the
* next request on the same connection MUST be put in the connectdata struct!
*************************************************************************/
union {
struct HTTP *http;
struct HTTP *https; /* alias, just for the sake of being more readable */
struct RTSP *rtsp;
struct FTP *ftp;
/* void *tftp; not used */
struct FILEPROTO *file;
void *telnet; /* private for telnet.c-eyes only */
void *generic;
struct SSHPROTO *ssh;
struct IMAP *imap;
struct POP3 *pop3;
struct SMTP *smtp;
} proto;
/* if true, force SSL connection retry (workaround for certain servers) */
bool ssl_connect_retry;
};
@@ -1387,6 +1370,8 @@ enum dupstring {
STRING_TLSAUTH_PASSWORD, /* TLS auth <password> */
#endif
STRING_BEARER, /* <bearer>, if used */
/* -- end of strings -- */
STRING_LAST /* not used, just an end-of-list marker */
};

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,6 +25,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "sslgen.h"
#include "http2.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
@@ -122,6 +123,11 @@ char *curl_version(void)
left -= len;
ptr += len;
#endif
#ifdef USE_NGHTTP2
len = Curl_http2_ver(ptr, left);
left -= len;
ptr += len;
#endif
#ifdef USE_LIBRTMP
{
char suff[2];
@@ -235,9 +241,6 @@ static curl_version_info_data version_info = {
#ifdef ENABLE_IPV6
| CURL_VERSION_IPV6
#endif
#ifdef HAVE_KRB4
| CURL_VERSION_KERBEROS4
#endif
#ifdef USE_SSL
| CURL_VERSION_SSL
#endif
@@ -277,6 +280,9 @@ static curl_version_info_data version_info = {
#endif
#if defined(USE_TLS_SRP)
| CURL_VERSION_TLSAUTH_SRP
#endif
#if defined(USE_NGHTTP2)
| CURL_VERSION_HTTP2
#endif
,
NULL, /* ssl_version */

View File

@@ -1479,7 +1479,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_PROTOTYPE_MISMATCH], [
return n;
}
]],[[
int i[2];
int i[2]={0,0};
int j = rand(i[0]);
if(j)
return j;

View File

@@ -70,6 +70,17 @@ $ write sys$output "Can not find VMS specific Curl readme file."
$ goto all_exit
$ endif
$!
$ curl_release_notes = f$search("sys$disk:[--]release-notes.")
$ if curl_release_notes .eqs. ""
$ then
$ curl_release_notes = f$search("sys$disk:[--]$RELEASE-NOTES.")
$ endif
$ if curl_release_notes .eqs. ""
$ then
$ write sys$output "Can not find Curl release-notes file."
$ goto all_exit
$ endif
$!
$ if f$search("sys$disk:[]hp_ssl_release_info.txt") .eqs. ""
$ then
$ write sys$output "GNV_LINK_CURL.COM has not been run!"
@@ -77,6 +88,7 @@ $ goto all_exit
$ endif
$!
$ type/noheader 'curl_readme', 'vms_readme', -
'curl_release_notes', -
sys$disk:[]curl_release_note_start.txt, -
sys$disk:[]hp_ssl_release_info.txt, -
'curl_copying', -

View File

@@ -375,14 +375,24 @@ $ if f$search("''file'.obj") .nes. "" then delete/log 'file'.obj;*
$ if f$search("''file'.opt") .nes. "" then delete/log 'file'.opt;*
$ file = "[...]curl-*_original_src.bck"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]curl_d-*_original_src.bck"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]curl-*_vms_src.bck"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]curl_d-*_vms_src.bck"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]curl-*.release_notes"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]curl_d-*.release_notes"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]*curl*.pcsi$desc"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]*curl_d*.pcsi$desc"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]*curl*.pcsi$text"
$ if f$search(file) .nes. "" then delete/log 'file';*
$ file = "[...]*curl_d*.pcsi$text"
$ if f$search(file) .nes. "" then delete/log 'file';*
$!
$ if clean_all .eq. 0 then goto Common_Exit
$ endif

View File

@@ -108,15 +108,36 @@ $!
$ file = "lcl_root:[.include.curl]curlbuild.h_old"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]curl-*_original_src.bck"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]curl_d-*_original_src.bck"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]curl-*_vms_src.bck"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]curl_d-*_vms_src.bck"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]curl-*.release_notes"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]curl_d-*.release_notes"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]*-curl-*.pcsi$desc"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]*-curl_d-*.pcsi$desc"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]*-curl-*.pcsi$text"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$ file = "lcl_root:[.packages.vms]*-curl_d-*.pcsi$text"
$ if f$search(file) .nes. "" then delete 'file';*
$!
$!======================================================================
$!
$ if p1 .nes. "REALCLEAN" then goto all_exit

View File

@@ -57,6 +57,11 @@ void free_config_fields(struct Configurable *config)
Curl_safefree(config->proxyuserpwd);
Curl_safefree(config->proxy);
Curl_safefree(config->dns_ipv6_addr);
Curl_safefree(config->dns_ipv4_addr);
Curl_safefree(config->dns_interface);
Curl_safefree(config->dns_servers);
Curl_safefree(config->noproxy);
Curl_safefree(config->mail_from);
@@ -96,6 +101,8 @@ void free_config_fields(struct Configurable *config)
Curl_safefree(config->krblevel);
Curl_safefree(config->trace_dump);
Curl_safefree(config->xoauth2_bearer);
config->trace_stream = NULL; /* closed elsewhere when appropriate */
Curl_safefree(config->writeout);
@@ -125,4 +132,3 @@ void free_config_fields(struct Configurable *config)
Curl_safefree(config->libcurl);
}

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -66,6 +66,10 @@ struct Configurable {
char *range;
long low_speed_limit;
long low_speed_time;
char *dns_servers; /* dot notation: 1.1.1.1;2.2.2.2 */
char *dns_interface; /* interface name */
char *dns_ipv4_addr; /* dot notation */
char *dns_ipv6_addr; /* dot notation */
int showerror; /* -1 == unset, default => show errors
0 => -s is used to NOT show errors
1 => -S has been used to show errors */
@@ -205,9 +209,12 @@ struct Configurable {
bool use_metalink; /* process given URLs as metalink XML file */
metalinkfile *metalinkfile_list; /* point to the first node */
metalinkfile *metalinkfile_last; /* point to the last/current node */
#ifdef CURLDEBUG
bool test_event_based;
#endif
char *xoauth2_bearer; /* XOAUTH2 bearer token */
}; /* struct Configurable */
void free_config_fields(struct Configurable *config);
#endif /* HEADER_CURL_TOOL_CFGABLE_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -73,10 +73,14 @@ static const struct LongShort aliases[]= {
/* all these ones, starting with "*" or "$" as a short-option have *no*
short option to mention. */
{"*", "url", TRUE},
{"*4", "dns-ipv4-addr", TRUE},
{"*6", "dns-ipv6-addr", TRUE},
{"*a", "random-file", TRUE},
{"*b", "egd-file", TRUE},
{"*B", "oauth2-bearer", TRUE},
{"*c", "connect-timeout", TRUE},
{"*d", "ciphers", TRUE},
{"*D", "dns-interface", TRUE},
{"*e", "disable-epsv", FALSE},
{"*E", "epsv", FALSE},
/* 'epsv' made like this to make --no-epsv and --epsv to work
@@ -84,6 +88,7 @@ static const struct LongShort aliases[]= {
#ifdef USE_ENVIRONMENT
{"*f", "environment", FALSE},
#endif
{"*F", "dns-servers", TRUE},
{"*g", "trace", TRUE},
{"*h", "trace-ascii", TRUE},
{"*i", "limit-rate", TRUE},
@@ -174,7 +179,10 @@ static const struct LongShort aliases[]= {
{"$I", "post303", FALSE},
{"$J", "metalink", FALSE},
{"$K", "sasl-ir", FALSE},
{"$L", "test-event", FALSE},
{"0", "http1.0", FALSE},
{"01", "http1.1", FALSE},
{"02", "http2.0", FALSE},
{"1", "tlsv1", FALSE},
{"2", "sslv2", FALSE},
{"3", "sslv3", FALSE},
@@ -283,7 +291,8 @@ static const struct feat feats[] = {
{"krb4", CURL_VERSION_KERBEROS4},
{"libz", CURL_VERSION_LIBZ},
{"CharConv", CURL_VERSION_CONV},
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
{"HTTP2", CURL_VERSION_HTTP2}
};
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
@@ -491,12 +500,23 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
switch(letter) {
case '*': /* options without a short option */
switch(subletter) {
case '4': /* --dns-ipv4-addr */
/* addr in dot notation */
GetStr(&config->dns_ipv4_addr, nextarg);
break;
case '6': /* --dns-ipv6-addr */
/* addr in dot notation */
GetStr(&config->dns_ipv6_addr, nextarg);
break;
case 'a': /* random-file */
GetStr(&config->random_file, nextarg);
break;
case 'b': /* egd-file */
GetStr(&config->egd_file, nextarg);
break;
case 'B': /* XOAUTH2 Bearer */
GetStr(&config->xoauth2_bearer, nextarg);
break;
case 'c': /* connect-timeout */
err = str2udouble(&config->connecttimeout, nextarg);
if(err)
@@ -505,6 +525,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
case 'd': /* ciphers */
GetStr(&config->cipher_list, nextarg);
break;
case 'D': /* --dns-interface */
/* interface name */
GetStr(&config->dns_interface, nextarg);
break;
case 'e': /* --disable-epsv */
config->disable_epsv = toggle;
break;
@@ -516,6 +540,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
config->writeenv = toggle;
break;
#endif
case 'F': /* --dns-servers */
/* IP addrs of DNS servers */
GetStr(&config->dns_servers, nextarg);
break;
case 'g': /* --trace */
GetStr(&config->trace_dump, nextarg);
if(config->tracetype && (config->tracetype != TRACE_BIN))
@@ -639,7 +667,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
case 'r': /* --create-dirs */
config->create_dirs = TRUE;
config->create_dirs = toggle;
break;
case 's': /* --max-redirs */
@@ -661,7 +689,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
case 'u': /* --crlf */
/* LF -> CRLF conversion? */
config->crlf = TRUE;
config->crlf = toggle;
break;
case 'v': /* --stderr */
@@ -888,7 +916,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
GetStr(&config->socks5_gssapi_service, nextarg);
break;
case '7': /* --socks5-gssapi-nec*/
config->socks5_gssapi_nec = TRUE;
config->socks5_gssapi_nec = toggle;
break;
#endif
case '8': /* --proxy1.0 */
@@ -959,7 +987,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
}
case 'K': /* --sasl-ir */
config->sasl_ir = TRUE;
config->sasl_ir = toggle;
break;
case 'L': /* --test-event */
#ifdef CURLDEBUG
config->test_event_based = toggle;
#else
warnf(config, "--test-event is ignored unless a debug build!\n");
#endif
break;
}
break;
@@ -972,10 +1007,22 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
case '~': /* --xattr */
config->xattr = toggle;
break;
case '0':
case '0': /* --http* options */
switch(subletter) {
case '\0':
/* HTTP version 1.0 */
config->httpversion = CURL_HTTP_VERSION_1_0;
break;
case '1':
/* HTTP version 1.1 */
config->httpversion = CURL_HTTP_VERSION_1_1;
break;
case '2':
/* HTTP version 2.0 */
config->httpversion = CURL_HTTP_VERSION_2_0;
break;
}
break;
case '1':
/* TLS version 1 */
config->ssl_version = CURL_SSLVERSION_TLSv1;
@@ -1621,20 +1668,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
}
break;
case 'u':
/* user:password */
/* user:password;options */
GetStr(&config->userpwd, nextarg);
cleanarg(nextarg);
err = checkpasswd("host", &config->userpwd);
if(err)
return err;
break;
case 'U':
/* Proxy user:password */
GetStr(&config->proxyuserpwd, nextarg);
cleanarg(nextarg);
err = checkpasswd("proxy", &config->proxyuserpwd);
if(err)
return err;
break;
case 'v':
if(toggle) {
@@ -1781,4 +1822,3 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
return PARAM_OK;
}

View File

@@ -69,6 +69,10 @@ static const char *const helptext[] = {
" --digest Use HTTP Digest Authentication (H)",
" --disable-eprt Inhibit using EPRT or LPRT (F)",
" --disable-epsv Inhibit using EPSV (F)",
" --dns-servers DNS server addrs to use: 1.1.1.1;2.2.2.2",
" --dns-interface Interface to use for DNS requests",
" --dns-ipv4-addr IPv4 address to use for DNS requests, dot notation",
" --dns-ipv6-addr IPv6 address to use for DNS requests, dot notation",
" -D, --dump-header FILE Write the headers to this file",
" --egd-file FILE EGD socket path for random data (SSL)",
" --engine ENGINE Crypto engine (SSL). \"--engine list\" for list",
@@ -99,6 +103,8 @@ static const char *const helptext[] = {
" --hostpubmd5 MD5 "
"Hex encoded MD5 string of the host public key. (SSH)",
" -0, --http1.0 Use HTTP 1.0 (H)",
" --http1.1 Use HTTP 1.1 (H)",
" --http2.0 Use HTTP 2.0 (H)",
" --ignore-content-length Ignore the HTTP Content-Length header",
" -i, --include Include protocol headers in the output (H/F)",
" -k, --insecure Allow connections to SSL sites without certs (H)",
@@ -119,9 +125,9 @@ static const char *const helptext[] = {
" -L, --location Follow redirects (H)",
" --location-trusted like --location and send auth to other hosts (H)",
" -M, --manual Display the full manual",
" --mail-from FROM Mail from this address",
" --mail-rcpt TO Mail to this receiver(s)",
" --mail-auth AUTH Originator address of the original email",
" --mail-from FROM Mail from this address (SMTP)",
" --mail-rcpt TO Mail to this/these addresses (SMTP)",
" --mail-auth AUTH Originator address of the original email (SMTP)",
" --max-filesize BYTES Maximum file size to download (H/F)",
" --max-redirs NUM Maximum number of redirects allowed (H)",
" -m, --max-time SECONDS Maximum time allowed for the transfer",
@@ -135,6 +141,7 @@ static const char *const helptext[] = {
" --no-sessionid Disable SSL session-ID reusing (SSL)",
" --noproxy List of hosts which do not use proxy",
" --ntlm Use HTTP NTLM authentication (H)",
" --oauth2-bearer BEARER XOAUTH2 Bearer Token (IMAP, POP3, SMTP)",
" -o, --output FILE Write output to <file> instead of stdout",
" --pass PASS Pass phrase for the private key (SSL/SSH)",
" --post301 "
@@ -173,7 +180,7 @@ static const char *const helptext[] = {
" --retry-delay SECONDS "
"When retrying, wait this many seconds between each",
" --retry-max-time SECONDS Retry only within this period",
" --sasl-ir Enable initial response in SASL authentication"
" --sasl-ir Enable initial response in SASL authentication",
" -S, --show-error "
"Show error. With -s, make curl show errors when they occur",
" -s, --silent Silent mode. Don't output anything",
@@ -243,4 +250,3 @@ void tool_help(void)
#endif
}
}

View File

@@ -69,6 +69,7 @@
#include "tool_msgs.h"
#include "tool_operate.h"
#include "tool_operhlp.h"
#include "tool_paramhlp.h"
#include "tool_parsecfg.h"
#include "tool_setopt.h"
#include "tool_sleep.h"
@@ -81,6 +82,11 @@
#include "memdebug.h" /* keep this as LAST include */
#ifdef CURLDEBUG
/* libcurl's debug builds provide an extra function */
CURLcode curl_easy_perform_ev(CURL *easy);
#endif
#define CURLseparator "--_curl_--"
#ifndef O_BINARY
@@ -196,6 +202,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
bool stillflags;
int res = 0;
int i;
unsigned long li;
bool orig_noprogress;
bool orig_isatty;
@@ -319,6 +326,18 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
}
}
if(config->userpwd && !config->xoauth2_bearer) {
res = checkpasswd("host", &config->userpwd);
if(res)
goto quit_curl;
}
if(config->proxyuserpwd) {
res = checkpasswd("proxy", &config->proxyuserpwd);
if(res)
goto quit_curl;
}
if((!config->url_list || !config->url_list->url) && !config->list_engines) {
helpf(config->errors, "no URL specified!\n");
res = CURLE_FAILED_INIT;
@@ -465,10 +484,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
int up; /* upload file counter within a single upload glob */
unsigned long up; /* upload file counter within a single upload glob */
char *infiles; /* might be a glob pattern */
char *outfiles;
int infilenum;
unsigned long infilenum;
URLGlob *inglob;
int metalink = 0; /* nonzero for metalink download. */
@@ -533,7 +552,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
char *uploadfile; /* a single file, never a glob */
int separator;
URLGlob *urls;
int urlnum;
unsigned long urlnum;
uploadfile = NULL;
urls = NULL;
@@ -583,7 +602,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
/* Here's looping around each globbed URL */
for(i = 0 ; i < urlnum; i++) {
for(li = 0 ; li < urlnum; li++) {
int infd;
bool infdopen;
@@ -628,7 +647,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
if(res)
goto show_error;
}
else if(!i) {
else if(!li) {
this_url = strdup(urlnode->url);
if(!this_url) {
res = CURLE_OUT_OF_MEMORY;
@@ -863,8 +882,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
}
if(urlnum > 1 && !(config->mute)) {
fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
fprintf(config->errors, "\n[%lu/%lu]: %s --> %s\n",
li+1, urlnum, this_url, outfile ? outfile : "<stdout>");
if(separator)
printf("%s%s\n", CURLseparator, this_url);
}
@@ -971,6 +990,9 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
else if(!config->use_metalink)
my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L);
if(config->xoauth2_bearer)
my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->xoauth2_bearer);
#if !defined(CURL_DISABLE_PROXY)
{
/* TODO: Make this a run-time check instead of compile-time one. */
@@ -1217,6 +1239,18 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
}
/* new in libcurl 7.24.0: */
if(config->dns_servers)
my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
/* new in libcurl 7.33.0: */
if(config->dns_interface)
my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
if(config->dns_ipv4_addr)
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
if(config->dns_ipv6_addr)
my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
/* new in libcurl 7.6.2: */
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
@@ -1449,6 +1483,11 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
mlfile->filename, this_url);
#endif /* USE_METALINK */
#ifdef CURLDEBUG
if(config->test_event_based)
res = curl_easy_perform_ev(curl);
else
#endif
res = curl_easy_perform(curl);
if(outs.is_cd_filename && outs.stream && !config->mute &&
@@ -1872,4 +1911,3 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
return res;
}

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -31,141 +31,146 @@
typedef enum {
GLOB_OK,
GLOB_NO_MEM,
GLOB_ERROR
GLOB_NO_MEM = CURLE_OUT_OF_MEMORY,
GLOB_ERROR = CURLE_URL_MALFORMAT
} GlobCode;
/*
* glob_word()
*
* Input a full globbed string, set the forth argument to the amount of
* strings we get out of this. Return GlobCode.
*/
static GlobCode glob_word(URLGlob *, /* object anchor */
char *, /* globbed string */
size_t, /* position */
int *); /* returned number of strings */
#define GLOBERROR(string, column, code) \
glob->error = string, glob->pos = column, code;
static GlobCode glob_set(URLGlob *glob, char *pattern,
size_t pos, int *amount)
void glob_cleanup(URLGlob* glob);
static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
{
URLPattern *pat = &glob->pattern[glob->size];
pat->type = UPTSet;
pat->content.Set.size = 1;
pat->content.Set.ptr_s = 0;
pat->globindex = -1;
(*amount)++;
pat->content.Set.elements = malloc(sizeof(char*));
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
pat->content.Set.elements[0] = strdup(glob->glob_buffer);
if(!pat->content.Set.elements[0])
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
return GLOB_OK;
}
/* multiply
*
* Multiplies and checks for overflow.
*/
static int multiply(unsigned long *amount, long with)
{
unsigned long sum = *amount * with;
if(sum/with != *amount)
return 1; /* didn't fit, bail out */
*amount = sum;
return 0;
}
static GlobCode glob_set(URLGlob *glob, char **patternp,
size_t *posp, unsigned long *amount,
int globindex)
{
/* processes a set expression with the point behind the opening '{'
','-separated elements are collected until the next closing '}'
*/
URLPattern *pat;
GlobCode res;
bool done = FALSE;
char *buf = glob->glob_buffer;
char *pattern = *patternp;
char *opattern = pattern;
size_t opos = *posp-1;
pat = &glob->pattern[glob->size / 2];
pat = &glob->pattern[glob->size];
/* patterns 0,1,2,... correspond to size=1,3,5,... */
pat->type = UPTSet;
pat->content.Set.size = 0;
pat->content.Set.ptr_s = 0;
pat->content.Set.elements = NULL;
if(++glob->size > (GLOB_PATTERN_NUM*2)) {
snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n");
return GLOB_ERROR;
}
pat->globindex = globindex;
while(!done) {
switch (*pattern) {
case '\0': /* URL ended while set was still open */
snprintf(glob->errormsg, sizeof(glob->errormsg),
"unmatched brace at pos %zu\n", pos);
return GLOB_ERROR;
return GLOBERROR("unmatched brace", opos, GLOB_ERROR);
case '{':
case '[': /* no nested expressions at this time */
snprintf(glob->errormsg, sizeof(glob->errormsg),
"nested braces not supported at pos %zu\n", pos);
return GLOB_ERROR;
return GLOBERROR("nested brace", *posp, GLOB_ERROR);
case ',':
case '}': /* set element completed */
if(opattern == pattern)
return GLOBERROR("empty string within braces", *posp, GLOB_ERROR);
/* add 1 to size since it'll be incremented below */
if(multiply(amount, pat->content.Set.size+1))
return GLOBERROR("range overflow", 0, GLOB_ERROR);
/* fall-through */
case ',':
*buf = '\0';
if(pat->content.Set.elements) {
char **new_arr = realloc(pat->content.Set.elements,
(pat->content.Set.size + 1) * sizeof(char*));
if(!new_arr) {
short elem;
for(elem = 0; elem < pat->content.Set.size; elem++)
Curl_safefree(pat->content.Set.elements[elem]);
Curl_safefree(pat->content.Set.elements);
pat->content.Set.ptr_s = 0;
pat->content.Set.size = 0;
}
if(!new_arr)
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
pat->content.Set.elements = new_arr;
}
else
pat->content.Set.elements = malloc(sizeof(char*));
if(!pat->content.Set.elements) {
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
return GLOB_NO_MEM;
}
if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
pat->content.Set.elements[pat->content.Set.size] =
strdup(glob->glob_buffer);
if(!pat->content.Set.elements[pat->content.Set.size]) {
short elem;
for(elem = 0; elem < pat->content.Set.size; elem++)
Curl_safefree(pat->content.Set.elements[elem]);
Curl_safefree(pat->content.Set.elements);
pat->content.Set.ptr_s = 0;
pat->content.Set.size = 0;
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
return GLOB_NO_MEM;
}
if(!pat->content.Set.elements[pat->content.Set.size])
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
++pat->content.Set.size;
if(*pattern == '}') {
/* entire set pattern completed */
int wordamount;
/* always check for a literal (may be "") between patterns */
res = glob_word(glob, ++pattern, ++pos, &wordamount);
if(res) {
short elem;
for(elem = 0; elem < pat->content.Set.size; elem++)
Curl_safefree(pat->content.Set.elements[elem]);
Curl_safefree(pat->content.Set.elements);
pat->content.Set.ptr_s = 0;
pat->content.Set.size = 0;
return res;
}
*amount = pat->content.Set.size * wordamount;
pattern++; /* pass the closing brace */
done = TRUE;
continue;
}
buf = glob->glob_buffer;
++pattern;
++pos;
++(*posp);
break;
case ']': /* illegal closing bracket */
snprintf(glob->errormsg, sizeof(glob->errormsg),
"illegal pattern at pos %zu\n", pos);
return GLOB_ERROR;
return GLOBERROR("unexpected close bracket", *posp, GLOB_ERROR);
case '\\': /* escaped character, skip '\' */
if(pattern[1]) {
++pattern;
++pos;
++(*posp);
}
/* intentional fallthrough */
default:
*buf++ = *pattern++; /* copy character to set element */
++pos;
++(*posp);
}
}
*patternp = pattern; /* return with the new position */
return GLOB_OK;
}
static GlobCode glob_range(URLGlob *glob, char *pattern,
size_t pos, int *amount)
static GlobCode glob_range(URLGlob *glob, char **patternp,
size_t *posp, unsigned long *amount,
int globindex)
{
/* processes a range expression with the point behind the opening '['
- char range: e.g. "a-z]", "B-Q]"
@@ -174,77 +179,68 @@ static GlobCode glob_range(URLGlob *glob, char *pattern,
expression is checked for well-formedness and collected until the next ']'
*/
URLPattern *pat;
char *c;
char sep;
char sep2;
int step;
int rc;
GlobCode res;
int wordamount = 1;
char *pattern = *patternp;
char *c;
pat = &glob->pattern[glob->size / 2];
/* patterns 0,1,2,... correspond to size=1,3,5,... */
if(++glob->size > (GLOB_PATTERN_NUM*2)) {
snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n");
return GLOB_ERROR;
}
pat = &glob->pattern[glob->size];
pat->globindex = globindex;
if(ISALPHA(*pattern)) {
/* character range detected */
char min_c;
char max_c;
int step=1;
pat->type = UPTCharRange;
rc = sscanf(pattern, "%c-%c%c%d%c", &min_c, &max_c, &sep, &step, &sep2);
rc = sscanf(pattern, "%c-%c", &min_c, &max_c);
if((rc < 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a'))) {
if((rc == 2) && (pattern[3] == ':')) {
char *endp;
unsigned long lstep;
errno = 0;
lstep = strtoul(&pattern[3], &endp, 10);
if(errno || (*endp != ']'))
step = -1;
else {
pattern = endp+1;
step = (int)lstep;
if(step > (max_c - min_c))
step = -1;
}
}
else
pattern+=3;
*posp += (pattern - *patternp);
if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
(step < 0) )
/* the pattern is not well-formed */
snprintf(glob->errormsg, sizeof(glob->errormsg),
"error: bad range specification after pos %zu\n", pos);
return GLOB_ERROR;
}
/* check the (first) separating character */
if((sep != ']') && (sep != ':')) {
snprintf(glob->errormsg, sizeof(glob->errormsg),
"error: unsupported character (%c) after range at pos %zu\n",
sep, pos);
return GLOB_ERROR;
}
return GLOBERROR("bad range", *posp, GLOB_ERROR);
/* if there was a ":[num]" thing, use that as step or else use 1 */
pat->content.CharRange.step =
((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1;
pat->content.CharRange.step = step;
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
pat->content.CharRange.max_c = max_c;
if(multiply(amount, (pat->content.CharRange.max_c -
pat->content.CharRange.min_c + 1)))
return GLOBERROR("range overflow", *posp, GLOB_ERROR);
}
else if(ISDIGIT(*pattern)) {
/* numeric range detected */
int min_n;
int max_n;
unsigned long min_n;
unsigned long max_n = 0;
unsigned long step_n = 0;
char *endp;
pat->type = UPTNumRange;
pat->content.NumRange.padlength = 0;
rc = sscanf(pattern, "%d-%d%c%d%c", &min_n, &max_n, &sep, &step, &sep2);
if((rc < 2) || (min_n > max_n)) {
/* the pattern is not well-formed */
snprintf(glob->errormsg, sizeof(glob->errormsg),
"error: bad range specification after pos %zu\n", pos);
return GLOB_ERROR;
}
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
pat->content.NumRange.max_n = max_n;
/* if there was a ":[num]" thing, use that as step or else use 1 */
pat->content.NumRange.step =
((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1;
if(*pattern == '0') {
/* leading zero specified */
/* leading zero specified, count them! */
c = pattern;
while(ISDIGIT(*c)) {
c++;
@@ -252,59 +248,74 @@ static GlobCode glob_range(URLGlob *glob, char *pattern,
instances of this pattern */
}
}
}
errno = 0;
min_n = strtoul(pattern, &endp, 10);
if(errno || (endp == pattern))
endp=NULL;
else {
snprintf(glob->errormsg, sizeof(glob->errormsg),
"illegal character in range specification at pos %zu\n", pos);
return GLOB_ERROR;
}
c = (char*)strchr(pattern, ']'); /* continue after next ']' */
if(c)
c++;
if(*endp != '-')
endp = NULL;
else {
snprintf(glob->errormsg, sizeof(glob->errormsg), "missing ']'");
return GLOB_ERROR; /* missing ']' */
pattern = endp+1;
errno = 0;
max_n = strtoul(pattern, &endp, 10);
if(errno || (*endp == ':')) {
pattern = endp+1;
errno = 0;
step_n = strtoul(pattern, &endp, 10);
if(errno)
/* over/underflow situation */
endp = NULL;
}
/* always check for a literal (may be "") between patterns */
res = glob_word(glob, c, pos + (c - pattern), &wordamount);
if(res == GLOB_ERROR) {
wordamount = 1;
res = GLOB_OK;
}
if(!res) {
if(pat->type == UPTCharRange)
*amount = wordamount * (pat->content.CharRange.max_c -
pat->content.CharRange.min_c + 1);
else
*amount = wordamount * (pat->content.NumRange.max_n -
pat->content.NumRange.min_n + 1);
step_n = 1;
if(endp && (*endp == ']')) {
pattern= endp+1;
}
else
endp = NULL;
}
}
return res; /* GLOB_OK or GLOB_NO_MEM */
*posp += (pattern - *patternp);
if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)))
/* the pattern is not well-formed */
return GLOBERROR("bad range", *posp, GLOB_ERROR);
/* typecasting to ints are fine here since we make sure above that we
are within 31 bits */
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
pat->content.NumRange.max_n = max_n;
pat->content.NumRange.step = step_n;
if(multiply(amount, (pat->content.NumRange.max_n -
pat->content.NumRange.min_n + 1)))
return GLOBERROR("range overflow", *posp, GLOB_ERROR);
}
else
return GLOBERROR("bad range specification", *posp, GLOB_ERROR);
*patternp = pattern;
return GLOB_OK;
}
static GlobCode glob_word(URLGlob *glob, char *pattern,
size_t pos, int *amount)
static GlobCode glob_parse(URLGlob *glob, char *pattern,
size_t pos, unsigned long *amount)
{
/* processes a literal string component of a URL
special characters '{' and '[' branch to set/range processing functions
*/
char* buf = glob->glob_buffer;
size_t litindex;
GlobCode res = GLOB_OK;
int globindex = 0; /* count "actual" globs */
*amount = 1; /* default is one single string */
while(*pattern != '\0' && *pattern != '{' && *pattern != '[') {
if(*pattern == '}' || *pattern == ']') {
snprintf(glob->errormsg, sizeof(glob->errormsg),
"unmatched close brace/bracket at pos %zu\n", pos);
return GLOB_ERROR;
}
while(*pattern && !res) {
int sublen = 0;
while(*pattern && *pattern != '{' && *pattern != '[') {
if(*pattern == '}' || *pattern == ']')
return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR);
/* only allow \ to escape known "special letters" */
if(*pattern == '\\' &&
@@ -317,47 +328,51 @@ static GlobCode glob_word(URLGlob *glob, char *pattern,
}
*buf++ = *pattern++; /* copy character to literal */
++pos;
sublen++;
}
if(sublen) {
/* we got a literal string, add it as a single-item list */
*buf = '\0';
litindex = glob->size / 2;
/* literals 0,1,2,... correspond to size=0,2,4,... */
glob->literal[litindex] = strdup(glob->glob_buffer);
if(!glob->literal[litindex]) {
snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n");
return GLOB_NO_MEM;
res = glob_fixed(glob, amount);
}
++glob->size;
else {
if(!*amount)
*amount = 1;
switch (*pattern) {
case '\0':
/* singular URL processed */
case '\0': /* done */
break;
case '{':
/* process set pattern */
res = glob_set(glob, ++pattern, ++pos, amount);
pattern++;
pos++;
res = glob_set(glob, &pattern, &pos, amount, globindex++);
break;
case '[':
/* process range pattern */
res = glob_range(glob, ++pattern, ++pos, amount);
pattern++;
pos++;
res = glob_range(glob, &pattern, &pos, amount, globindex++);
break;
}
}
if(res)
Curl_safefree(glob->literal[litindex]);
if(++glob->size > GLOB_PATTERN_NUM)
return GLOBERROR("too many globs", pos, GLOB_ERROR);
}
return res;
}
int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error)
int glob_url(URLGlob** glob, char* url, unsigned long *urlnum, FILE *error)
{
/*
* We can deal with any-size, just make a buffer with the same length
* as the specified URL!
*/
URLGlob *glob_expand;
int amount;
unsigned long amount = 0;
char *glob_buffer;
GlobCode res;
@@ -372,26 +387,31 @@ int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error)
Curl_safefree(glob_buffer);
return CURLE_OUT_OF_MEMORY;
}
glob_expand->size = 0;
glob_expand->urllen = strlen(url);
glob_expand->glob_buffer = glob_buffer;
glob_expand->beenhere = 0;
res = glob_word(glob_expand, url, 1, &amount);
res = glob_parse(glob_expand, url, 1, &amount);
if(!res)
*urlnum = amount;
else {
if(error && glob_expand->errormsg[0]) {
if(error && glob_expand->error) {
char text[128];
const char *t;
if(glob_expand->pos) {
snprintf(text, sizeof(text), "%s in column %zu", glob_expand->error,
glob_expand->pos);
t = text;
}
else
t = glob_expand->error;
/* send error description to the error-stream */
fprintf(error, "curl: (%d) [globbing] %s",
(res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT,
glob_expand->errormsg);
fprintf(error, "curl: (%d) [globbing] %s\n", res, t);
}
/* it failed, we cleanup */
Curl_safefree(glob_buffer);
Curl_safefree(glob_expand);
glob_cleanup(glob_expand);
*urlnum = 1;
return (res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT;
return res;
}
*glob = glob_expand;
@@ -404,19 +424,14 @@ void glob_cleanup(URLGlob* glob)
int elem;
for(i = glob->size - 1; i < glob->size; --i) {
if(!(i & 1)) { /* even indexes contain literals */
Curl_safefree(glob->literal[i/2]);
}
else { /* odd indexes contain sets or ranges */
if((glob->pattern[i/2].type == UPTSet) &&
(glob->pattern[i/2].content.Set.elements)) {
for(elem = glob->pattern[i/2].content.Set.size - 1;
if((glob->pattern[i].type == UPTSet) &&
(glob->pattern[i].content.Set.elements)) {
for(elem = glob->pattern[i].content.Set.size - 1;
elem >= 0;
--elem) {
Curl_safefree(glob->pattern[i/2].content.Set.elements[elem]);
}
Curl_safefree(glob->pattern[i/2].content.Set.elements);
Curl_safefree(glob->pattern[i].content.Set.elements[elem]);
}
Curl_safefree(glob->pattern[i].content.Set.elements);
}
}
Curl_safefree(glob->glob_buffer);
@@ -426,7 +441,6 @@ void glob_cleanup(URLGlob* glob)
int glob_next_url(char **globbed, URLGlob *glob)
{
URLPattern *pat;
char *lit;
size_t i;
size_t j;
size_t len;
@@ -442,7 +456,7 @@ int glob_next_url(char **globbed, URLGlob *glob)
/* implement a counter over the index ranges of all patterns,
starting with the rightmost pattern */
for(i = glob->size / 2 - 1; carry && (i < glob->size); --i) {
for(i = glob->size - 1; carry && (i < glob->size); --i) {
carry = FALSE;
pat = &glob->pattern[i];
switch (pat->type) {
@@ -480,14 +494,7 @@ int glob_next_url(char **globbed, URLGlob *glob)
}
for(j = 0; j < glob->size; ++j) {
if(!(j&1)) { /* every other term (j even) is a literal */
lit = glob->literal[j/2];
len = snprintf(buf, buflen, "%s", lit);
buf += len;
buflen -= len;
}
else { /* the rest (i odd) are patterns */
pat = &glob->pattern[j/2];
pat = &glob->pattern[j];
switch(pat->type) {
case UPTSet:
if(pat->content.Set.elements) {
@@ -502,7 +509,7 @@ int glob_next_url(char **globbed, URLGlob *glob)
*buf++ = pat->content.CharRange.ptr_c;
break;
case UPTNumRange:
len = snprintf(buf, buflen, "%0*d",
len = snprintf(buf, buflen, "%0*ld",
pat->content.NumRange.padlength,
pat->content.NumRange.ptr_n);
buf += len;
@@ -513,7 +520,6 @@ int glob_next_url(char **globbed, URLGlob *glob)
return CURLE_FAILED_INIT;
}
}
}
*buf = '\0';
*globbed = strdup(glob->glob_buffer);
@@ -549,34 +555,44 @@ int glob_match_url(char **result, char *filename, URLGlob *glob)
unsigned long i;
char *ptr = filename;
unsigned long num = strtoul(&filename[1], &filename, 10);
i = num - 1UL;
URLPattern *pat =NULL;
if(num && (i <= glob->size / 2)) {
URLPattern pat = glob->pattern[i];
switch (pat.type) {
if(num < glob->size) {
num--; /* make it zero based */
/* find the correct glob entry */
for(i=0; i<glob->size; i++) {
if(glob->pattern[i].globindex == (int)num) {
pat = &glob->pattern[i];
break;
}
}
}
if(pat) {
switch (pat->type) {
case UPTSet:
if(pat.content.Set.elements) {
appendthis = pat.content.Set.elements[pat.content.Set.ptr_s];
if(pat->content.Set.elements) {
appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
appendlen =
strlen(pat.content.Set.elements[pat.content.Set.ptr_s]);
strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
}
break;
case UPTCharRange:
numbuf[0] = pat.content.CharRange.ptr_c;
numbuf[0] = pat->content.CharRange.ptr_c;
numbuf[1] = 0;
appendthis = numbuf;
appendlen = 1;
break;
case UPTNumRange:
snprintf(numbuf, sizeof(numbuf), "%0*d",
pat.content.NumRange.padlength,
pat.content.NumRange.ptr_n);
pat->content.NumRange.padlength,
pat->content.NumRange.ptr_n);
appendthis = numbuf;
appendlen = strlen(numbuf);
break;
default:
printf("internal error: invalid pattern type (%d)\n",
(int)pat.type);
fprintf(stderr, "internal error: invalid pattern type (%d)\n",
(int)pat->type);
Curl_safefree(target);
return CURLE_FAILED_INIT;
}

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, 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
@@ -31,11 +31,13 @@ typedef enum {
typedef struct {
URLPatternType type;
int globindex; /* the number of this particular glob or -1 if not used
within {} or [] */
union {
struct {
char **elements;
short size;
short ptr_s;
int size;
int ptr_s;
} Set;
struct {
char min_c;
@@ -44,29 +46,29 @@ typedef struct {
int step;
} CharRange;
struct {
int min_n;
int max_n;
short padlength;
int ptr_n;
int step;
unsigned long min_n;
unsigned long max_n;
int padlength;
unsigned long ptr_n;
unsigned long step;
} NumRange ;
} content;
} URLPattern;
/* the total number of globs supported */
#define GLOB_PATTERN_NUM 9
#define GLOB_PATTERN_NUM 100
typedef struct {
char *literal[10];
URLPattern pattern[GLOB_PATTERN_NUM+1];
URLPattern pattern[GLOB_PATTERN_NUM];
size_t size;
size_t urllen;
char *glob_buffer;
char beenhere;
char errormsg[80]; /* error message buffer */
const char *error; /* error message */
size_t pos; /* column position of error or 0 */
} URLGlob;
int glob_url(URLGlob**, char*, int *, FILE *);
int glob_url(URLGlob**, char*, unsigned long *, FILE *);
int glob_next_url(char **, URLGlob *);
int glob_match_url(char **, char*, URLGlob *);
void glob_cleanup(URLGlob* glob);

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,13 +23,18 @@
#ifdef HAVE_FSETXATTR
# include <sys/xattr.h> /* header from libc, not from libattr */
# define USE_XATTR
#elif defined(__FreeBSD_version) && (__FreeBSD_version > 500000)
# include <sys/types.h>
# include <sys/extattr.h>
# define USE_XATTR
#endif
#include "tool_xattr.h"
#include "memdebug.h" /* keep this as LAST include */
#ifdef HAVE_FSETXATTR
#ifdef USE_XATTR
/* mapping table of curl metadata to extended attribute names */
static const struct xattr_mapping {
@@ -60,6 +65,12 @@ int fwrite_xattr(CURL *curl, int fd)
err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0, 0);
#elif defined(HAVE_FSETXATTR_5)
err = fsetxattr(fd, mappings[i].attr, value, strlen(value), 0);
#elif defined(__FreeBSD_version)
err = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, mappings[i].attr, value,
strlen(value));
/* FreeBSD's extattr_set_fd returns the length of the extended attribute
*/
err = err < 0 ? err : 0;
#endif
}
i++;

View File

@@ -125,6 +125,13 @@ SLOWDOWN
- Send FTP responses with 0.01 sec delay between each byte
PASVBADIP
- makes PASV send back an illegal IP in its 227 response
CAPA [capabilities]
- Enables support for and specifies a list of space separated capabilities to
return to the client for the IMAP CAPABILITY, POP3 CAPA and SMTP EHLO
commands
AUTH [mechanisms]
- Enables support for SASL authentication and specifies a list of space
separated mechanisms for IMAP, POP3 and SMTP
For HTTP/HTTPS:
auth_required if this is set and a POST/PUT is made without auth, the
@@ -144,6 +151,10 @@ rtp: part [num] channel [num] size [num]
connection-monitor When used, this will log [DISCONNECT] to the server.input
log when the connection is disconnected.
For TFTP:
writedelay: [secs] delay this amount between reply packets (each packet being
512 bytes payload)
</servercmd>
</reply>

View File

@@ -64,12 +64,14 @@ test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 \
\
test800 test801 test802 test803 test804 test805 test806 test807 test808 \
test809 \
test809 test810 test811 test812 test813 test814 \
\
test850 test851 test852 test853 test854 test855 test856 test857 \
test850 test851 test852 test853 test854 test855 test856 test857 test858 \
test859 test860 test861 test862 \
\
test900 test901 test902 test903 test904 test905 test906 test907 test908 \
test909 test910 test911 \
test909 test910 test911 test912 test913 test914 test915 test916 test917 \
test918 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -93,7 +95,8 @@ test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
test1228 test1229 test1230 test1231 test1232 test1233 \
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
test1236 test1237 test1238 test1239 \
\
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
@@ -110,7 +113,7 @@ test1388 test1389 test1390 test1391 test1392 test1393 test1394 test1395 \
test1396 \
\
test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
test1408 test1409 test1410 test1412 test1413 test1414 \
test1408 test1409 test1410 test1412 test1413 test1414 test1415 \
\
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 test1511 test1512 \

View File

@@ -89,7 +89,7 @@ ftps
FTPS download with strict timeout and slow data transfer
</name>
<command timeout="1">
-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/1112 -m 7
-k --ftp-ssl-control ftps://%HOSTIP:%FTPSPORT/1112 -m 16
</command>
</client>

32
tests/data/test1234 Normal file
View File

@@ -0,0 +1,32 @@
<testcase>
<info>
<keywords>
{} list
FAILURE
</keywords>
</info>
# Server-side
<reply>
</reply>
# Client-side
<client>
<server>
none
</server>
<name>
abusing {}-globbing
</name>
<command>
"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/{}{}{}{"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
# 3 == CURLE_URL_MALFORMAT
<errorcode>
3
</errorcode>
</verify>
</testcase>

94
tests/data/test1235 Normal file
View File

@@ -0,0 +1,94 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
{} list
</keywords>
</info>
# Server-side
<reply>
<data1>
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 15
the number one
</data1>
<data2>
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 16
two is nice too
</data2>
</reply>
# Client-side
<client>
<server>
http
</server>
<name>
multiple requests using {}{} in the URL
</name>
<command>
"%HOSTIP:%HTTPPORT/{1235,1235}{0001,0002}"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /12350001 HTTP/1.1
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
Host: %HOSTIP:%HTTPPORT
Accept: */*
GET /12350002 HTTP/1.1
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
Host: %HOSTIP:%HTTPPORT
Accept: */*
GET /12350001 HTTP/1.1
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
Host: %HOSTIP:%HTTPPORT
Accept: */*
GET /12350002 HTTP/1.1
User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
<stdout>
--_curl_--%HOSTIP:%HTTPPORT/12350001
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 15
the number one
--_curl_--%HOSTIP:%HTTPPORT/12350002
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 16
two is nice too
--_curl_--%HOSTIP:%HTTPPORT/12350001
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 15
the number one
--_curl_--%HOSTIP:%HTTPPORT/12350002
HTTP/1.1 200 OK
Funny-head: yesyes
Content-Length: 16
two is nice too
</stdout>
</verify>
</testcase>

33
tests/data/test1236 Normal file
View File

@@ -0,0 +1,33 @@
<testcase>
<info>
<keywords>
globbing
FAILURE
</keywords>
</info>
# Server-side
<reply>
</reply>
# Client-side
<client>
<server>
none
</server>
<name>
[] globbing overflowing the range counter
</name>
# 2^62 == 4611686018427387904
<command>
"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/[1-4611686018427387904][1-4611686018427387904]"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
# 3 == CURLE_URL_MALFORMAT
<errorcode>
3
</errorcode>
</verify>
</testcase>

47
tests/data/test1237 Normal file
View File

@@ -0,0 +1,47 @@
<testcase>
<info>
<keywords>
HTTP
Basic
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Server: test-server/fake
Content-Length: 6
Connection: close
Content-Type: text/html
-foo-
</data>
</reply>
# Client-side
<client>
<server>
http
</server>
<name>
URL with 1000+ letter user name + password
</name>
<command>
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB@%HOSTIP:%HTTPPORT/1237"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1237 HTTP/1.1
Authorization: Basic QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQTpCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI=
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

49
tests/data/test1238 Normal file
View File

@@ -0,0 +1,49 @@
<testcase>
<info>
<keywords>
TFTP
TFTP RRQ
</keywords>
</info>
#
# Server-side
<reply>
<servercmd>
writedelay: 1
</servercmd>
# ~1200 bytes (so that they don't fit in two 512 byte chunks)
<data nocheck="yes">
012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
</data>
</reply>
#
# Client-side
<client>
<server>
tftp
</server>
<name>
slow TFTP retrieve cancel due to -Y and -y
</name>
# if less than 1000 bytes/sec within 2 seconds, abort!
<command>
tftp://%HOSTIP:%TFTPPORT//1238 -Y1000 -y2
</command>
</client>
#
# Verify pseudo protocol after the test has been "shot"
<verify>
<protocol>
opcode: 1
filename: /1238
mode: octet
</protocol>
# 28 = CURLE_OPERATION_TIMEDOUT
<errorcode>
28
</errorcode>
</verify>
</testcase>

68
tests/data/test1239 Normal file
View File

@@ -0,0 +1,68 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
-z
</keywords>
</info>
#
# Server-side
<reply>
<data nocheck="yes">
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2010 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
-foo-
</data>
</reply>
#
# Client-side
<client>
<server>
http
</server>
<name>
HTTP with -z + -w response_code and simulated 304
</name>
<command>
http://%HOSTIP:%HTTPPORT/1239 -z "-dec 12 12:00:00 1999 GMT" -w '%{response_code}'
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1239 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
If-Unmodified-Since: Sun, 12 Dec 1999 12:00:00 GMT
</protocol>
<stdout nonewline="yes">
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2010 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
304
</stdout>
</verify>
</testcase>

View File

@@ -35,7 +35,7 @@ To: another
body
</stdin>
<command>
smtp://smtp.1320:%SMTPPORT/user --mail-rcpt 1320@foo --mail-rcpt 1320@foobar.example --mail-from 1320@from -T - -p -x %HOSTIP:%PROXYPORT
smtp://smtp.1320:%SMTPPORT/1320 --mail-rcpt recipient@example.com --mail-from sender@example.com -T - -p -x %HOSTIP:%PROXYPORT
</command>
</client>
@@ -46,10 +46,9 @@ smtp://smtp.1320:%SMTPPORT/user --mail-rcpt 1320@foo --mail-rcpt 1320@foobar.exa
^User-Agent: curl/.*
</strip>
<protocol>
EHLO user
MAIL FROM:<1320@from>
RCPT TO:<1320@foo>
RCPT TO:<1320@foobar.example>
EHLO 1320
MAIL FROM:<sender@example.com>
RCPT TO:<recipient@example.com>
DATA
QUIT
</protocol>

View File

@@ -11,6 +11,9 @@ SMTP
#
# Server-side
<reply>
<servercmd>
CAPA SIZE
</servercmd>
</reply>
#
@@ -29,7 +32,7 @@ To: another
body
</file>
<command>
smtp://%HOSTIP:%SMTPPORT/user --mail-rcpt 1406@foo --mail-rcpt 1406@foobar.example --mail-from 1406@from -T log/test1406.eml --libcurl log/test1406.c
smtp://%HOSTIP:%SMTPPORT/1406 --mail-rcpt recipient.one@example.com --mail-rcpt recipient.two@example.com --mail-from sender@example.com -T log/test1406.eml --libcurl log/test1406.c
</command>
</client>
@@ -37,10 +40,10 @@ smtp://%HOSTIP:%SMTPPORT/user --mail-rcpt 1406@foo --mail-rcpt 1406@foobar.examp
# Verify data after the test has been "shot"
<verify>
<protocol>
EHLO user
MAIL FROM:<1406@from> SIZE=38
RCPT TO:<1406@foo>
RCPT TO:<1406@foobar.example>
EHLO 1406
MAIL FROM:<sender@example.com> SIZE=38
RCPT TO:<recipient.one@example.com>
RCPT TO:<recipient.two@example.com>
DATA
QUIT
</protocol>
@@ -65,19 +68,19 @@ int main(int argc, char *argv[])
struct curl_slist *slist1;
slist1 = NULL;
slist1 = curl_slist_append(slist1, "1406@foo");
slist1 = curl_slist_append(slist1, "1406@foobar.example");
slist1 = curl_slist_append(slist1, "recipient.one@example.com");
slist1 = curl_slist_append(slist1, "recipient.two@example.com");
hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)38);
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/user");
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406");
curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "1406@from");
curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com");
curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1);
/* Here is a list of options the curl code used that cannot get generated

72
tests/data/test1415 Normal file
View File

@@ -0,0 +1,72 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
cookies
cookiejar
delete expired cookie
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Content-Length: 4
Content-Type: text/html
Funny-head: yesyes
Set-Cookie: test1value=test1; domain=example.com; path=/;
Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
Set-Cookie: test3value=test3; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
Set-Cookie: test5value=test5; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
Set-Cookie: test6value=test6; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
Set-Cookie: test8value=test8; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
boo
</data>
</reply>
# Client-side
<client>
<server>
http
</server>
<name>
Delete expired cookies
</name>
<setenv>
TZ=GMT
</setenv>
<command>
http://example.com/we/want/1415 -b none -c log/jar1415.txt -x %HOSTIP:%HTTPPORT
</command>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET http://example.com/we/want/1415 HTTP/1.1
Host: example.com
Accept: */*
Proxy-Connection: Keep-Alive
</protocol>
<file name="log/jar1415.txt" mode="text">
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
.example.com TRUE / FALSE 0 test1value test1
.example.com TRUE / FALSE 2114380800 test2value test2
.example.com TRUE / FALSE 2114380800 test4value test4
.example.com TRUE / FALSE 2114380800 test7value test7
</file>
</verify>
</testcase>

View File

@@ -32,7 +32,7 @@ To: another
body
</stdin>
<command>
smtp://%HOSTIP:%SMTPPORT/user
smtp://%HOSTIP:%SMTPPORT/1507
</command>
</client>
@@ -40,7 +40,7 @@ smtp://%HOSTIP:%SMTPPORT/user
# Verify data after the test has been "shot"
<verify>
<protocol>
EHLO user
EHLO 1507
MAIL FROM:<1507-realuser@example.com>
RCPT TO:<1507-recipient@example.com>
DATA

View File

@@ -123,22 +123,22 @@ chkhostname curlhost
<protocol>
GET /20320100 HTTP/1.1
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
GET /20320100 HTTP/1.1
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
GET /20320200 HTTP/1.1
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
GET /20320200 HTTP/1.1
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
</protocol>

View File

@@ -124,22 +124,22 @@ chkhostname curlhost
<protocol>
GET /20320100 HTTP/1.1
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
GET /20320100 HTTP/1.1
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
GET /20320200 HTTP/1.1
Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
GET /20320200 HTTP/1.1
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAABoIBAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q=
Host: 127.0.0.1:8990
Host: 127.0.0.1:%HTTPPORT
Accept: */*
</protocol>

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