Compare commits

...

200 Commits

Author SHA1 Message Date
Daniel Stenberg
85c710e11e RELEASE-NOTES: synced with 0de7249bb3 - 7.31.0 2013-06-22 11:30:31 +02:00
Daniel Stenberg
0de7249bb3 unit1396: unit tests to verify curl_easy_(un)escape 2013-06-22 11:21:35 +02:00
Daniel Stenberg
192c4f788d Curl_urldecode: no peeking beyond end of input buffer
Security problem: CVE-2013-2174

If a program would give a string like "%FF" to curl_easy_unescape() but
ask for it to decode only the first byte, it would still parse and
decode the full hex sequence. The function then not only read beyond the
allowed buffer but it would also deduct the *unsigned* counter variable
for how many more bytes there's left to read in the buffer by two,
making the counter wrap. Continuing this, the function would go on
reading beyond the buffer and soon writing beyond the allocated target
buffer...

Bug: http://curl.haxx.se/docs/adv_20130622.html
Reported-by: Timo Sirainen
2013-06-22 11:21:35 +02:00
Guenter Knauf
da0db499fd Use opened body.out file and write content to it. 2013-06-20 22:53:37 +02:00
Daniel Stenberg
88c5c63ffc multi_socket: react on socket close immediately
As a remedy to the problem when a socket gets closed and a new one is
opened with the same file descriptor number and as a result
multi.c:singlesocket() doesn't detect the difference, the new function
Curl_multi_closed() gets told when a socket is closed so that it can be
removed from the socket hash. When the old one has been removed, a new
socket should be detected fine by the singlesocket() on next invoke.

Bug: http://curl.haxx.se/bug/view.cgi?id=1248
Reported-by: Erik Johansson
2013-06-20 22:36:52 +02:00
Daniel Stenberg
a9f5ad0e2a RELEASE-NOTES: synced with e305f5ec71 2013-06-20 22:27:33 +02:00
Daniel Stenberg
e305f5ec71 TODO: mention the DANE patch from March 2013-06-18 09:38:06 +02:00
Daniel Stenberg
7ac3e9f1ba CURLOPT_COOKIELIST: take cookie share lock
When performing COOKIELIST operations the cookie lock needs to be taken
for the cases where the cookies are shared among multiple handles!

Verified by Benjamin Gilbert's updated test 506

Bug: http://curl.haxx.se/bug/view.cgi?id=1215
Reported-by: Benjamin Gilbert
2013-06-17 23:29:05 +02:00
Benjamin Gilbert
03a3dd9ee3 test506: verify that CURLOPT_COOKIELIST takes share lock
It doesn't right now: http://curl.haxx.se/bug/view.cgi?id=1215
2013-06-17 23:28:35 +02:00
Daniel Stenberg
5fc24a5297 TODO: HTTP2/SPDY support 2013-06-15 14:36:35 +02:00
Daniel Stenberg
b1a295ac4e curl_easy_setopt.3: clarify CURLOPT_PROGRESSFUNCTION frequency
Make it clearer that the CURLOPT_PROGRESSFUNCTION callback will be
called more frequently than once per second when things are happening.
2013-06-14 23:17:14 +02:00
Daniel Stenberg
1826c768ab RELEASE-NOTES: synced with 9c3e098259
Mention 7 recent bug fixes and their associated contributors
2013-06-13 23:01:32 +02:00
Daniel Stenberg
9c3e098259 curl_multi_wait.3: clarify the numfds counter 2013-06-13 22:38:53 +02:00
Daniel Stenberg
0feeab7802 curl_easy_perform: avoid busy-looping
When curl_multi_wait() finds no file descriptor to wait for, it returns
instantly and this must be handled gracefully within curl_easy_perform()
or cause a busy-loop. Starting now, repeated fast returns without any
file descriptors is detected and a gradually increasing sleep will be
used (up to a max of 1000 milliseconds) before continuing the loop.

Bug: http://curl.haxx.se/bug/view.cgi?id=1238
Reported-by: Miguel Angel
2013-06-13 19:27:12 +02:00
YAMADA Yasuharu
f24dc09d20 cookies: follow-up fix for path checking
The initial fix to only compare full path names were done in commit
04f52e9b4d but found out to be incomplete. This takes should make the
change more complete and there's now two additional tests to verify
(test 31 and 62).
2013-06-12 11:19:56 +02:00
Sergei Nikulov
9e10963c20 lib1900: use tutil_tvnow instead of gettimeofday
Makes it build on windows
2013-06-12 10:52:23 +02:00
Eric Hu
10b6d81c64 axtls: now done non-blocking 2013-06-12 10:37:32 +02:00
Eric Hu
8026bd7abd test2033: requires NTLM support 2013-06-12 10:34:10 +02:00
Daniel Stenberg
9b8df58169 KNOWN_BUGS: #82 failed build with Borland compiler 2013-06-11 00:21:16 +02:00
Daniel Stenberg
529a2e9110 Curl_output_digest: support auth-int for empty entity body
By always returning the md5 for an empty body when auth-int is asked
for, libcurl now at least sometimes does the right thing.

Bug: http://curl.haxx.se/bug/view.cgi?id=1235
Patched-by: Nach M. S.
2013-06-11 00:08:13 +02:00
Daniel Stenberg
21091549c0 multi_socket: reduce timeout inaccuracy margin
Allow less room for "triggered too early" mistakes by applications /
timers on non-windows platforms. Starting now, we assume that a timeout
call is never made earlier than 3 milliseconds before the actual
timeout. This greatly improves timeout accuracy on Linux.

Bug: http://curl.haxx.se/bug/view.cgi?id=1228
Reported-by: Hang Su
2013-06-11 00:02:29 +02:00
Daniel Stenberg
7b97f03f09 cert_stuff: avoid double free in the PKCS12 code
In the pkcs12 code, we get a list of x509 records returned from
PKCS12_parse but when iterating over the list and passing each to
SSL_CTX_add_extra_chain_cert() we didn't also properly remove them from
the "stack", which made them get freed twice (both in sk_X509_pop_free()
and then later in SSL_CTX_free).

This isn't really documented anywhere...

Bug: http://curl.haxx.se/bug/view.cgi?id=1236
Reported-by: Nikaiw
2013-06-10 23:42:48 +02:00
Daniel Stenberg
ce362e8eb9 cert_stuff: remove code duplication in the pkcs12 logic 2013-06-10 23:04:01 +02:00
Aleksey Tulinov
a4decb49a6 axtls: honor disabled VERIFYHOST
When VERIFYHOST == 0, libcurl should let invalid certificates to pass.
2013-06-08 00:23:05 +02:00
Peter Gal
c53fb36b0c curl_easy_setopt.3: HTTP header with no content
Update the documentation on how to specify a HTTP header with no
content.
2013-06-08 00:15:40 +02:00
Daniel Stenberg
dc19e656b5 RELEASE-NOTES: synced with 87cf677eca
Added 11 bugs and 7 contributors
2013-06-07 10:39:21 +02:00
Daniel Stenberg
87cf677eca lib1500: remove bad check
After curl_multi_wait() returns, this test checked that we got exactly
one file descriptor told to read from, but we cannot be sure that is
true. curl_multi_wait() will sometimes return earlier without any file
descriptor to handle, just just because it is a suitable time to call
*perform().

This problem showed up with commit 29bf0598.

Bug: http://curl.haxx.se/mail/lib-2013-06/0029.html
Reported-by: Fabian Keil
2013-06-06 22:22:14 +02:00
Daniel Stenberg
5657c56f63 tests/Makefile: typo in the perlcheck target
Bug: http://curl.haxx.se/bug/view.cgi?id=1239
Reported-by: Christian Weisgerber
2013-06-04 23:22:11 +02:00
Daniel Stenberg
51b3445e84 test1230: verify CONNECT to a numerical ipv6-address 2013-06-04 22:52:13 +02:00
Daniel Stenberg
a7452b8b8c sws: support extracting test number from CONNECT ipv6-address!
If an ipv6-address is provided to CONNECT, the last hexadecimal group in
the address will be used as the test number! For example the address
"[1234::ff]" would be treated as test case 255.
2013-06-04 22:50:58 +02:00
Daniel Stenberg
0bf5ce77aa curl_multi_wait: only use internal timer if not -1
commit 29bf0598aa introduced a problem when the "internal" timeout is
prefered to the given if shorter, as it didn't consider the case where
-1 was returned. Now the internal timeout is only considered if not -1.

Reported-by: Tor Arntsen
Bug: http://curl.haxx.se/mail/lib-2013-06/0015.html
2013-06-04 13:22:40 +02:00
Dan Fandrich
159d34b58e libcurl-tutorial.3: added a section on IPv6
Also added a (correctly-escaped) backslash to the autoexec.bat
example file and a new Windows character device name with
a colon as examples of other characters that are special
and potentially dangerous (this reverts and reworks commit
7d8d2a54).
2013-06-03 22:44:05 +02:00
Daniel Stenberg
29bf0598aa curl_multi_wait: reduce timeout if the multi handle wants to
If the multi handle's pending timeout is less than what is passed into
this function, it will now opt to use the shorter time anyway since it
is a very good hint that the handle wants to process something in a
shorter time than what otherwise would happen.

curl_multi_wait.3 was updated accordingly to clarify

This is the reason for bug #1224

Bug: http://curl.haxx.se/bug/view.cgi?id=1224
Reported-by: Andrii Moiseiev
2013-06-03 20:27:08 +02:00
Daniel Stenberg
239b58d34d multi_runsingle: switch an if() condition for readability
... because there's an identical check right next to it so using the
operators in the check in the same order increases readability.
2013-06-03 20:23:01 +02:00
Marc Hoersken
74f1810546 curl_schannel.c: Removed variable unused since 35874298e4 2013-06-02 20:21:42 +02:00
Marc Hoersken
f4b08b8f40 curl_setup.h: Fixed redefinition warning using mingw-w64 2013-06-02 15:53:08 +02:00
Daniel Stenberg
6691fdf517 multi_runsingle: add braces to clarify the code 2013-05-30 23:34:33 +02:00
Daniel Stenberg
7d8d2a54ba libcurl-tutorial.3: remove incorrect backslash
A single backslash in the content is not legal nroff syntax.

Reported and fixed by: Eric S. Raymond
Bug: http://curl.haxx.se/bug/view.cgi?id=1234
2013-05-28 13:37:08 +02:00
Daniel Stenberg
9986c6cb2b curl_formadd.3: fixed wrong "end-marker" syntax
Reported and fixed by: Eric S. Raymond
Bug: http://curl.haxx.se/bug/view.cgi?id=1233
2013-05-28 13:35:13 +02:00
Daniel Stenberg
ba9a66663a curl.1: clarify that --silent still outputs data 2013-05-28 11:37:58 +02:00
Daniel Stenberg
ac419bf562 Digest auth: escape user names with \ or " in them
When sending the HTTP Authorization: header for digest, the user name
needs to be escaped if it contains a double-quote or backslash.

Test 1229 was added to verify

Reported and fixed by: Nach M. S
Bug: http://curl.haxx.se/bug/view.cgi?id=1230
2013-05-27 19:45:12 +02:00
Mike Giancola
520833cbe1 ossl_recv: SSL_read() returning 0 is an error too
SSL_read can return 0 for "not successful", according to the open SSL
documentation: http://www.openssl.org/docs/ssl/SSL_read.html
2013-05-22 23:42:33 +02:00
Mike Giancola
e58d9c87f7 ossl_send: SSL_write() returning 0 is an error too
We found that in specific cases if the connection is abruptly closed,
the underlying socket is listed in a close_wait state. We continue to
call the curl_multi_perform, curl_mutli_fdset etc. None of these APIs
report the socket closed / connection finished.  Since we have cases
where the multi connection is only used once, this can pose a problem
for us. I've read that if another connection was to come in, curl would
see the socket as bad and attempt to close it at that time -
unfortunately, this does not work for us.

I found that in specific situations, if SSL_write returns 0, curl did
not recognize the socket as closed (or errored out) and did not report
it to the application. I believe we need to change the code slightly, to
check if ssl_write returns 0. If so, treat it as an error - the same as
a negative return code.

For OpenSSL - the ssl_write documentation is here:
http://www.openssl.org/docs/ssl/SSL_write.html
2013-05-22 23:08:27 +02:00
Daniel Stenberg
84f7991474 KNOWN_BUGS: curl -OJC- fails to resume
Bug: http://curl.haxx.se/bug/view.cgi?id=1169
2013-05-21 23:58:52 +02:00
Daniel Stenberg
85b9dc8023 Curl_cookie_add: handle IPv6 hosts
1 - don't skip host names with a colon in them in an attempt to bail out
on HTTP headers in the cookie file parser. It was only a shortcut anyway
and trying to parse a file with HTTP headers will still be handled, only
slightly slower.

2 - don't skip domain names based on number of dots. The original
netscape cookie spec had this oddity mentioned and while our code
decreased the check to only check for two, the existing cookie spec has
no such dot counting required.

Bug: http://curl.haxx.se/bug/view.cgi?id=1221
Reported-by: Stefan Neis
2013-05-21 23:28:59 +02:00
Daniel Stenberg
7d4d4892d8 curl_easy_setopt.3: expand the PROGRESSFUNCTION section
Explain the callback and its arguments better and with more descriptive
text.
2013-05-20 10:50:51 +02:00
Daniel Stenberg
fc4759af9d tests: add test1394 file to the tarball 2013-05-19 12:44:44 +02:00
Daniel Stenberg
ee84c47655 tarball: include the xmlstream example 2013-05-19 11:21:56 +02:00
David Strauss
ce32176db7 xmlstream: XML stream parsing example source code
Add an XML stream parsing example using Expat. Add missing ignore for
the binary from an unrelated example.
2013-05-19 11:19:28 +02:00
YAMADA Yasuharu
04f52e9b4d cookies: only consider full path matches
I found a bug which cURL sends cookies to the path not to aim at.
For example:
- cURL sends a request to http://example.fake/hoge/
- server returns cookie which with path=/hoge;
  the point is there is NOT the '/' end of path string.
- cURL sends a request to http://example.fake/hogege/ with the cookie.

The reason for this old "feature" is because that behavior is what is
described in the original netscape cookie spec:
http://curl.haxx.se/rfc/cookie_spec.html

The current cookie spec (RFC6265) clarifies the situation:
http://tools.ietf.org/html/rfc6265#section-5.2.4
2013-05-18 22:54:48 +02:00
Eric Hu
100a33f7ff axtls: prevent memleaks on SSL handshake failures 2013-05-16 20:26:42 +02:00
Daniel Stenberg
7ed25ccf0d Revert "WIN32 MemoryTracking: track wcsdup() _wcsdup() and _tcsdup() usage"
This reverts commit 8ec2cb5544.

We don't have any code anywhere in libcurl (or the curl tool) that use
wcsdup so there's no such memory use to track. It seems to cause mild
problems with the Borland compiler though that we may avoid by reverting
this change again.

Bug: http://curl.haxx.se/mail/lib-2013-05/0070.html
2013-05-12 15:10:01 +02:00
Daniel Stenberg
01eede2662 RELEASE-NOTES: synced with ae26ee3489 2013-05-12 14:36:04 +02:00
Guenter Knauf
ae26ee3489 Updated zlib version in build files. 2013-05-11 17:08:00 +02:00
Renaud Guillard
992bee504d OS X framework: fix invalid symbolic link 2013-05-09 21:51:35 +02:00
Daniel Stenberg
01a2abedd7 nss: give PR_INTERVAL_NO_WAIT instead of -1 to PR_Recv/PR_Send
Reported by: David Strauss
Bug: http://curl.haxx.se/mail/lib-2013-05/0088.html
2013-05-09 11:23:15 +02:00
Daniel Stenberg
a45e3f93e4 libtest: gitignore more binary files 2013-05-08 14:35:45 +02:00
Daniel Stenberg
bdb396ef2a servercert: allow empty subject
Bug: http://curl.haxx.se/bug/view.cgi?id=1220
Patch by: John Gardiner Myers
2013-05-07 23:02:01 +02:00
Steve Holme
6add1901a1 tests: Added new SMTP tests to verify commit 99b4045183 2013-05-07 22:52:43 +02:00
Daniel Stenberg
51b0f09b5e runtests.pl: support nonewline="yes" in client/stdin sections 2013-05-07 22:52:43 +02:00
Daniel Stenberg
8dac7be438 build: fixed unit1394 for debug and metlink builds 2013-05-06 23:28:04 +02:00
Kamil Dudka
bcf1b9dec1 unit1394.c: plug the curl tool unit test in 2013-05-06 15:03:13 +02:00
Jared Jennings
b045d079f8 unit1394.c: basis of a unit test for parse_cert_parameter() 2013-05-06 15:03:13 +02:00
Kamil Dudka
683f2b8323 src/Makefile.am: build static lib for unit tests if enabled 2013-05-06 15:03:12 +02:00
Kamil Dudka
2de20dd9a1 tool_getparam: ensure string termination in parse_cert_parameter() 2013-05-06 15:00:10 +02:00
Kamil Dudka
b47cf4f688 tool_getparam: fix memleak in handling the -E option 2013-05-06 15:00:10 +02:00
Kamil Dudka
a15b2b6c62 tool_getparam: describe what parse_cert_parameter() does
... and de-duplicate the code initializing *passphrase
2013-05-06 15:00:10 +02:00
Kamil Dudka
42e01cff9a curl.1: document escape sequences recognized by -E 2013-05-06 14:32:26 +02:00
Jared Jennings
865d4138a0 curl -E: allow to escape ':' in cert nickname 2013-05-06 14:32:26 +02:00
Marc Hoersken
35874298e4 curl_schannel.c: Fixed invalid memory access during SSL shutdown 2013-05-05 17:57:37 +02:00
Steve Holme
52d72e66c2 smtp: Fix trailing whitespace warning 2013-05-04 18:37:50 +01:00
Steve Holme
f3d10aa0d4 smtp: Fix compilation warning
comparison between signed and unsigned integer expressions
2013-05-04 13:24:05 +01:00
Steve Holme
7632bc911b RELEASE-NOTES: synced with 92ef5f19c8 2013-05-04 10:13:43 +01:00
Steve Holme
92ef5f19c8 smtp: Updated RFC-2821 references to RFC-5321 2013-05-04 10:12:01 +01:00
Steve Holme
99b4045183 smtp: Fixed sending of double CRLF caused by first in EOB
If the mail sent during the transfer contains a terminating <CRLF> then
we should not send the first <CRLF> of the EOB as specified in RFC-5321.

Additionally don't send the <CRLF> if there is "no mail data" as the
DATA command already includes it.
2013-05-04 10:00:33 +01:00
Steve Holme
087f9bb20a tests: Corrected MAIL SIZE for CRLF line endings
... which was missed in commit: f5c3d95384
2013-05-03 20:08:21 +01:00
Steve Holme
e2c7e19144 tests: Corrected infilesize for CRLF line endings
... which was missed in commit: f5c3d95384
2013-05-03 18:27:06 +01:00
Steve Holme
f5c3d95384 tests: Corrected test1406 to be RFC2821 compliant 2013-05-03 18:22:18 +01:00
Steve Holme
6b10f5b963 tests: Corrected test1320 to be RFC2821 compliant 2013-05-02 22:49:16 +01:00
Steve Holme
ee74b77d45 tests: Corrected typo in test909
Introduced in commit: 514817669e
2013-05-02 20:03:50 +01:00
Steve Holme
734bdb68c2 tests: Corrected test909 to be RFC2821 compliant 2013-05-02 18:52:52 +01:00
Steve Holme
514817669e tests: Updated test references to 909 from 1411
...and removed references to libcurl and test1406.
2013-05-02 18:50:00 +01:00
Steve Holme
cb9c0ac7d7 tests: Renamed test1411 to test909 as this is a main SMTP test 2013-05-02 18:46:11 +01:00
Lars Johannesen
1c435295b8 bindlocal: move brace out of #ifdef
The code within #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID wrongly had two
closing braces when it should only have one, so builds without that
define would fail.

Bug: http://curl.haxx.se/mail/lib-2013-05/0000.html
2013-05-01 14:18:47 +02:00
Steve Holme
46d26a0e77 smtp: Tidy up to move the eob counter to the per-request structure
Move the eob counter from the smtp_conn structure to the SMTP structure
as it is associated with a SMTP payload on a per-request basis.
2013-04-30 22:25:23 +01:00
Steve Holme
f4e3cae8a7 TODO: Updated following the addition of CURLOPT_SASL_IR 2013-04-30 00:12:41 +01:00
Steve Holme
b52cf5d2cd smtp: Fixed unknown percentage complete in progress bar
The curl command line utility would display the the completed progress
bar with a percentage of zero as the progress routines didn't know the
size of the transfer.
2013-04-29 22:34:26 +01:00
Daniel Stenberg
073e83b543 ftpserver: silence warnings
Fix regressions in commit b56e3d43e5. Make @data local and filter off
non-numerical digits from $testno in STATUS_imap.
2013-04-29 14:58:08 +02:00
Steve Holme
c3e6d69acb ftpserver.pl: Corrected the imap LOGIN response
...to be more realistic and consistent with the other imap responses.
2013-04-29 12:58:41 +01:00
Steve Holme
b56e3d43e5 tests: Added imap STATUS command test 2013-04-29 12:53:09 +01:00
Steve Holme
f317ffb7bb tests: Corrected the SMTP tests to be RFC2821 compliant
The emails that are sent to the server during these tests were
incorrectly formatted as they contained one or more LF terminated lines
rather than being CRLF terminated as per Section 2.3.7 of RFC-2821.

This wasn't a problem for the test suite as the <stdin> data matched the
<upload> data but anyone using these tests as reference would be sending
incorrect data to a server.
2013-04-28 16:14:58 +01:00
Steve Holme
9ea5145952 email: Tidy up of *_perform_authenticate()
Removed the hard returns from imap and pop3 by using the same style for
sending the authentication string as smtp. Moved the "Other mechanisms
not supported" check in smtp to match that of imap and pop3 to provide
consistency between the three email protocols.
2013-04-28 12:57:42 +01:00
Steve Holme
1d7c38e1f0 smtp: Updated limit check to be more readable like the check in pop3 2013-04-28 12:26:44 +01:00
Steve Holme
18bfc8f2d7 pop3: Added 255 octet limit check when sending initial response
Added 255 octet limit check as per Section 4. Paragraph 8 of RFC-5034.
2013-04-28 12:26:11 +01:00
Steve Holme
945246988d DOCS: Corrected line length of recent Secure Transport changes 2013-04-28 12:17:15 +01:00
Nick Zitzmann
a5c0e20939 darwinssl: add TLS crypto authentication
Users using the Secure Transport (darwinssl) back-end can now use a
certificate and private key to authenticate with a site using TLS. Because
Apple's security system is based around the keychain and does not have any
non-public function to create a SecIdentityRef data structure from data
loaded outside of the Keychain, the certificate and private key have to be
loaded into the Keychain first (using the certtool command line tool or
the Security framework's C API) before we can find it and use it.
2013-04-27 23:15:07 -06:00
Steve Holme
128517649c Corrected version numbers after bump 2013-04-27 23:02:20 +01:00
Daniel Stenberg
219358b93d bump version
Since we're adding new stuff, the next release will bump the minor
version and we're looking forward to 7.31.0
2013-04-27 23:15:35 +02:00
Steve Holme
f133719f73 RELEASE-NOTES: synced with f4e6e201b1 2013-04-27 20:43:55 +01:00
Steve Holme
f4e6e201b1 DOCS: Updated following the addition of CURLOPT_SASL_IR
Documented the the option in curl_easy_setopt() and added it to
symbols-in-versions.
2013-04-27 17:08:08 +01:00
Steve Holme
790b2086d7 tests: Corrected command line arguments in test907 and test908 2013-04-27 16:36:17 +01:00
Steve Holme
f9b691cdb0 tests: Added SMTP AUTH with initial response tests 2013-04-27 13:04:02 +01:00
Steve Holme
4118c30261 tests: Updated SMTP tests to decouple client initial response
Updated test903 and test904 following the addition of CURLOPT_SASL_IR
as the default behaviour of SMTP AUTH responses is now to not include
the initial response. New tests with --sasl-ir support to follow.
2013-04-27 12:32:27 +01:00
Steve Holme
dacbdaab94 imap: Added support for overriding the SASL initial response
In addition to checking for the SASL-IR capability the user can override
the sending of the client's initial response in the AUTHENTICATION
command with the use of CURLOPT_SASL_IR should the server erroneously
not report SASL-IR when it does support it.
2013-04-27 12:12:59 +01:00
Steve Holme
70e30f6caa smtp: Added support for disabling the SASL initial response
Updated the default behaviour of sending the client's initial response in the AUTH
command to not send it and added support for CURLOPT_SASL_IR to allow the user to
specify including the response.

Related Bug: http://curl.haxx.se/mail/lib-2012-03/0114.html
Reported-by: Gokhan Sengun
2013-04-27 12:09:15 +01:00
Steve Holme
7cb6c31370 pop3: Added support for enabling the SASL initial response
Allowed the user to specify whether to send the client's intial response
in the AUTH command via CURLOPT_SASL_IR.
2013-04-27 12:07:39 +01:00
Steve Holme
5d3a031ca7 sasl-ir: Added --sasl-ir option to curl command line tool 2013-04-27 10:03:10 +01:00
Steve Holme
a846fbbe2a sasl-ir: Added CURLOPT_SASL_IR to enable/disable the SASL initial response 2013-04-27 09:58:20 +01:00
Daniel Stenberg
6420672879 curl_easy_init: use less mallocs
By introducing an internal alternative to curl_multi_init() that accepts
parameters to set the hash sizes, easy handles will now use tiny socket
and connection hash tables since it will only ever add a single easy
handle to that multi handle.

This decreased the number mallocs in test 40 (which is a rather simple
and typical easy interface use case) from 1142 to 138. The maximum
amount of memory allocated used went down from 118969 to 78805.
2013-04-26 22:55:55 +02:00
Steve Holme
c4067a5678 ftpserver.pl: Fixed imap logout confirmation data
An IMAP server should response with the BYE continuation response before
confirming the LOGOUT command was successful.
2013-04-26 21:12:36 +01:00
Daniel Stenberg
0523152ad6 ftp_state_pasv_resp: connect through proxy also when set by env
When connecting back to an FTP server after having sent PASV/EPSV,
libcurl sometimes didn't use the proxy properly even though the proxy
was used for the initial connect.

The function wrongly checked for the CURLOPT_PROXY variable to be set,
which made it act wrongly if the proxy information was set with an
environment variable.

Added test case 711 to verify (based on 707 which uses --socks5). Also
added test712 to verify another variation of setting the proxy: with
--proxy socks5://

Bug: http://curl.haxx.se/bug/view.cgi?id=1218
Reported-by: Zekun Ni
2013-04-26 16:49:25 +02:00
Zdenek Pavlas
b37b5233ca url: initialize speed-check data for file:// protocol
... in order to prevent an artificial timeout event based on stale
speed-check data from a previous network transfer.  This commit fixes
a regression caused by 9dd85bced5.

Bug: https://bugzilla.redhat.com/906031
2013-04-26 15:38:22 +02:00
Daniel Stenberg
c68c7e588e test709: clarify the test in the name 2013-04-25 23:42:38 +02:00
Daniel Stenberg
1498a0073e sshserver: disable StrictHostKeyChecking
I couldn't figure out why the host key logic isn't working, but having
it set to yes prevents my SSH-based test cases to run. I also don't see
a strong need to use strict host key checking on this test server.

So I disabled it.
2013-04-25 23:40:31 +02:00
Daniel Stenberg
27777949a0 runtests: log more commands in verbose mode
... to aid tracking down failures
2013-04-25 23:40:01 +02:00
Steve Holme
4dc2d965d6 TODO: Corrected copy/paste typo 2013-04-25 20:18:08 +01:00
Steve Holme
70bbbccc39 TODO: Added new ideas for future SMTP, POP3 and IMAP features 2013-04-25 20:10:09 +01:00
Steve Holme
0dd470fc61 TODO: Updated following the addition of ;auth=<MECH> support 2013-04-25 19:48:34 +01:00
Steve Holme
89acdf50fa DOCS: Minor rewording / clarification of host name protocol detection 2013-04-25 13:30:17 +01:00
Steve Holme
c0d502785f RELEASE-NOTES: synced with a8c92cb608 2013-04-24 19:40:06 +01:00
Steve Holme
a8c92cb608 DOCS: Added reference to IETF draft for SMTP URL Interface
...when mentioning login options. Additional minor clarification of
"Windows builds" to be "Windows builds with SSPI"as a way of enabling
NTLM as Windows builds may be built with OpenSSL to enable NTLM or
without NTLM support altogether.
2013-04-24 19:35:38 +01:00
Linus Nielsen Feltzing
53fda844cc HISTORY: Fix spelling error. 2013-04-23 21:41:38 +02:00
Steve Holme
bbf63b0faa DOCS: Reworked the scheme calculation explanation under CURLOPT_URL 2013-04-23 19:57:58 +01:00
Steve Holme
2af9fd4960 url: Added smtp and pop3 hostnames to the protocol detection list 2013-04-23 19:44:14 +01:00
Daniel Stenberg
2c0d65785f HISTORY: correct some years/dates
Thanks to archive.org's wayback machine I updated this document with
some facts from the early httpget/urlget web page:

http://web.archive.org/web/19980216125115/http://www.inf.ufrgs.br/~sagula/urlget.html
2013-04-23 16:21:29 +02:00
Alessandro Ghedini
d791179d7f tests: add test1511 to check timecond clean-up
Verifies the timecond fix in commit c49ed0b6c0
2013-04-22 22:46:47 +02:00
Alessandro Ghedini
c49ed0b6c0 getinfo.c: reset timecond when clearing session-info variables
Bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=705783
Reported-by: Ludovico Cavedon <cavedon@debian.org>
2013-04-22 22:43:32 +02:00
Steve Holme
868d8e6831 DOCS: Added information about login options to CURLOPT_USERPWD 2013-04-22 20:22:12 +01:00
Steve Holme
e3aca1b2ce DOCS: Added information about login options in the URL 2013-04-22 20:22:10 +01:00
Steve Holme
ddac43b38e url: Fixed missing length check in parse_proxy()
Commit 11332577b3 removed the length check that was performed by the
old scanf() code.
2013-04-21 18:29:33 +01:00
Steve Holme
416ecc1584 url: Fixed crash when no username or password supplied for proxy
Fixed an issue in parse_proxy(), introduced in commit 11332577b3,
where an empty username or password (For example: http://:@example.com)
would cause a crash.
2013-04-21 16:55:19 +01:00
Steve Holme
455ba691a7 url: Removed unused text length constants 2013-04-21 12:16:12 +01:00
Steve Holme
11332577b3 url: Updated proxy URL parsing to use parse_login_details() 2013-04-21 12:12:29 +01:00
Steve Holme
702b0dd408 url: Tidy up of setstropt_userpwd() parameters
Updated the naming convention of the login parameters to match those of
other functions.
2013-04-21 10:27:42 +01:00
Steve Holme
e8a9f794f0 url: Tidy up of code and comments following recent changes
Tidy up of variable names and comments in setstropt_userpwd() and
parse_login_details().
2013-04-21 10:23:47 +01:00
Steve Holme
bddf3d4705 url: Simplified setstropt_userpwd() following recent changes
There is no need to perform separate clearing of data if a NULL option
pointer is passed in. Instead this operation can be performed by simply
not calling parse_login_details() and letting the rest of the code do
the work.
2013-04-20 20:04:00 +01:00
Steve Holme
e99c81a07c url: Correction to scope of if statements when setting data 2013-04-20 19:10:10 +01:00
Steve Holme
fe880475ed url: Fixed memory leak in setstropt_userpwd()
setstropt_userpwd() was calling setstropt() in commit fddb7b44a7 to
set each of the login details which would duplicate the strings and
subsequently cause a memory leak.
2013-04-20 18:40:13 +01:00
Steve Holme
5821d5f111 RELEASE-NOTES: synced with d535c4a2e1 2013-04-20 09:56:16 +01:00
Steve Holme
d535c4a2e1 url: Added overriding of URL login options from CURLOPT_USERPWD 2013-04-20 09:18:51 +01:00
Steve Holme
ca8f17a303 tool_paramhlp: Fixed options being included in username
Fix to prevent the options from being displayed when curl requests the
user's password if the following command line is specified:

--user username;options
2013-04-20 09:16:21 +01:00
Steve Holme
fddb7b44a7 url: Added support for parsing login options from the CURLOPT_USERPWD
In addition to parsing the optional login options from the URL, added
support for parsing them from CURLOPT_USERPWD, to allow the following
supported command line:

--user username:password;options
2013-04-20 09:08:28 +01:00
Steve Holme
49184c3723 url: Added bounds checking to parse_login_details()
Added bounds checking when searching for the separator characters within
the login string as this string may not be NULL terminated (For example
it is the login part of a URL). We do this in preference to allocating a
new string to copy the login details into which could then be passed to
parse_login_details() for performance reasons.
2013-04-19 19:37:55 +01:00
Steve Holme
cc7f6a2ddf url: Added size_t cast to pointer based length calculations 2013-04-19 14:11:43 +01:00
Steve Holme
90fe59b829 url: Corrected minor typo in comment 2013-04-19 12:53:59 +01:00
Daniel Stenberg
7b074a460b CURL_CHECK_CA_BUNDLE: don't check for paths when cross-compiling
When cross-compiling we can't scan and detect existing files or paths.

Bug: http://curl.haxx.se/mail/lib-2013-04/0294.html
2013-04-18 23:37:56 +02:00
Ishan SinghLevett
993cdcd6ee usercertinmem.c: add example showing user cert in memory
Relies on CURLOPT_SSL_CTX_FUNCTION, which is OpenSSL specific
2013-04-18 23:07:15 +02:00
Steve Holme
8763374f0e url: Fix chksrc longer than 79 columns warning 2013-04-18 20:21:11 +01:00
Steve Holme
63388fe1f3 url: Fix incorrect variable type for result code 2013-04-18 19:18:02 +01:00
Steve Holme
b75a88aa72 url: Fix compiler warning
signed and unsigned type in conditional expression
2013-04-18 19:14:25 +01:00
Steve Holme
bb20989a63 url: Moved parsing of login details out of parse_url_login()
Separated the parsing of login details from the processing of them in
parse_url_login() ready for use by setstropt_userpwd().
2013-04-18 18:09:53 +01:00
Steve Holme
0d49e408a4 url: Re-factored set_userpass() and parse_url_userpass()
Re-factored these functions to reflect their new behaviour following the
addition of login options.
2013-04-18 17:36:15 +01:00
Steve Holme
90c87f311e url: Reworked URL parsing to allow overriding by CURLOPT_USERPWD 2013-04-18 17:20:43 +01:00
Daniel Stenberg
da06ac7f3f maketgz: make bzip2 creation work with Parallel BZIP2 too
Apparently the previous usage didn't work with that implementation,
while this updated version works with at least both Parallel BZIP2
v1.1.8 and regular bzip "Version 1.0.6, 6-Sept-2010".
2013-04-18 11:13:56 +02:00
Linus Nielsen Feltzing
6d9236e805 Add tests/http_pipe.py to the tarball build 2013-04-18 10:55:41 +02:00
Steve Holme
c306d2e42f smtp: Re-factored all perform based functions
Standardised the naming of all perform based functions to be in the form
smtp_perform_something().
2013-04-16 19:48:20 +01:00
Steve Holme
f737e3a3dd smtp: Added description comments to all perform based functions 2013-04-16 19:44:53 +01:00
Steve Holme
686586b0f9 smtp: Moved smtp_quit() to be with the other perform functions 2013-04-16 19:44:52 +01:00
Steve Holme
e621a5f6ea smtp: Moved smtp_rcpt_to() to be with the other perform functions 2013-04-16 19:44:49 +01:00
Steve Holme
8093f9541e smtp: Moved smtp_mail() to be with the other perform functions 2013-04-16 19:44:47 +01:00
Wouter Van Rooy
68e7fb499d curl-config: don't output static libs when they are disabled
Curl-config outputs static libraries even when they are disabled in
configure.

This causes problems with the build of pycurl.
2013-04-16 16:07:41 +02:00
Dave Reisner
d9569720dd docs/libcurl: fix formatting in manpage
Commit c3ea3eb6 introduced some minor cosmetic errors in
curl_mutli_socket_action(3).
2013-04-16 09:52:12 +02:00
Paul Howarth
1c40685d32 Add extra libs for lib1900 and lib2033 test programs
These are needed in cases where clock_gettime is used, from librt.
2013-04-15 23:06:10 +02:00
Dan Fandrich
31c6e7af6a FAQ: mention that the network connection can be monitored
Also note the prohibition on sharing handles across threads.
2013-04-15 22:26:18 +02:00
Steve Holme
552ba67bb1 pop3: Added missing comment for pop3_state_apop_resp() 2013-04-15 20:27:49 +01:00
Steve Holme
651254dcc7 smtp: Updated the coding style of smtp_state_servergreet_resp()
Updated the coding style, in this function, to be consistant with other
response functions rather then performing a hard return on failure.
2013-04-15 20:27:47 +01:00
Steve Holme
26bdafcbf9 pop3: Updated the coding style of pop3_state_servergreet_resp()
Updated the coding style, in this function, to be consistent with other
response functions rather then performing a hard return on failure.
2013-04-15 20:27:45 +01:00
Steve Holme
02dc9e788f pop3: Re-factored all perform based functions
Standardised the naming of all perform based functions to be in the form
pop3_perform_something() following the changes made to IMAP.
2013-04-14 10:06:10 +01:00
Steve Holme
e11c6e9961 pop3: Added description comments to all perform based functions 2013-04-14 10:06:08 +01:00
Steve Holme
e4eaa92728 pop3: Moved pop3_quit() to be with the other perform functions 2013-04-14 10:06:07 +01:00
Steve Holme
577f8e5ac6 pop3: Moved pop3_command() to be with the other perform functions
Started to apply the same tidy up to the POP3 code as applied to the
IMAP code in the 7.30.0 release.
2013-04-14 10:06:05 +01:00
Steve Holme
95ba6cdd54 RELEASE-NOTES: Removed erroneous spaces 2013-04-13 18:35:16 +01:00
Steve Holme
7ce6cb9ab4 RELEASE-NOTES: synced with 8723cade21 2013-04-13 16:43:30 +01:00
Steve Holme
8723cade21 smtp: Added support for ;auth=<mech> in the URL
Added support for specifying the preferred authentication mechanism in
the URL as per Internet-Draft 'draft-earhart-url-smtp-00'.
2013-04-13 16:23:00 +01:00
Steve Holme
d956d9db47 pop3: Reworked authentication type constants
... to use left-shifted values, like those defined in curl.h, rather
than 16-bit hexadecimal values.
2013-04-13 16:20:48 +01:00
Steve Holme
ecf93ac986 pop3: Small consistency tidy up 2013-04-13 16:16:23 +01:00
Steve Holme
b3a01be2f3 pop3: Added support for ;auth=<mech> in the URL
Added support for specifying the preferred authentication type and SASL
mechanism in the URL as per RFC-2384.
2013-04-13 16:16:21 +01:00
Steve Holme
00045a3009 imap: Added support for ;auth=<mech> in the URL
Added support for specifying the preferred authentication mechanism in
the URL as per RFC-5092.
2013-04-13 16:11:27 +01:00
Steve Holme
3f7188dd94 sasl: Reworked SASL mechanism constants
... to use left-shifted values, like those defined in curl.h, rather
than 16-bit hexadecimal values.
2013-04-13 13:29:50 +01:00
Steve Holme
720218fea1 sasl: Added predefined preferred mechanism values
In preparation for the upcoming changes to IMAP, POP3 and SMTP added
preferred mechanism values.
2013-04-13 13:11:37 +01:00
Steve Holme
73aa95592f url: Added support for parsing login options from the URL
As well as parsing the username and password from the URL, added support
for parsing the optional options part from the login details, to allow
the following supported URL format:

schema://username:password;options@example.com/path?q=foobar

This will only be used by IMAP, POP3 and SMTP at present but any
protocol that may be given login options in the URL will be able to
add support for them.
2013-04-13 10:49:42 +01:00
Steve Holme
ad3fdbc0a4 smtp: Fix compiler warning
warning: unused variable 'smtp' introduced in commit 73cbd21b5e.
2013-04-13 00:06:19 +01:00
Steve Holme
73cbd21b5e smtp: Moved parsing of url path into separate function 2013-04-12 23:15:51 +01:00
Daniel Stenberg
c5ba0c2f54 FTP: handle a 230 welcome response
...instead of the 220 we otherwise expect.

Made the ftpserver.pl support sending a custom "welcome" and then
created test 1219 to verify this fix with such a 230 welcome.

Bug: http://curl.haxx.se/mail/lib-2013-02/0102.html
Reported by: Anders Havn
2013-04-12 23:59:37 +02:00
Daniel Stenberg
edddf394b8 configure: try pthread_create without -lpthread
For libc variants without a spearate pthread lib (like bionic), try
using pthreads without the pthreads lib first and only if that fails try
the -lpthread linker flag.

Bug: http://curl.haxx.se/bug/view.cgi?id=1216
Reported by: Duncan
2013-04-12 22:58:28 +02:00
Daniel Stenberg
61d259f950 FTP: access files in root dir correctly
Accessing a file with an absolute path in the root dir but with no
directory specified was not handled correctly. This fix comes with four
new test cases that verify it.

Bug: http://curl.haxx.se/mail/lib-2013-04/0142.html
Reported by: Sam Deane
2013-04-12 22:43:13 +02:00
Steve Holme
c01735865f pop3: Reworked the function description for Curl_pop3_write() 2013-04-12 20:22:14 +01:00
Steve Holme
ca46c5dbe2 pop3: Added function description to pop3_parse_custom_request() 2013-04-12 20:22:12 +01:00
Steve Holme
2da127abb5 pop3: Moved utility functions to end of pop3.c 2013-04-12 20:22:10 +01:00
Nick Zitzmann
bc33f2200d darwinssl: add TLS session resumption
This ought to speed up additional TLS handshakes, at least in theory.
2013-04-12 12:20:10 -06:00
Steve Holme
fd399cde00 imap: Added function description to imap_parse_custom_request() 2013-04-12 18:27:51 +01:00
Steve Holme
00c74019f4 imap: Moved utility functions to end of imap.c (Part 3/3)
Moved imap_is_bchar() be with the other utility based functions.
2013-04-12 18:24:46 +01:00
Steve Holme
9d0063befa imap: Moved utility functions to end of imap.c (Part 2/3)
Moved imap_parse_url_path() and imap_parse_custom_request() to the end of the
file allowing all utility functions to be grouped together.
2013-04-12 18:24:44 +01:00
Steve Holme
01e55ebb26 imap: Moved utility functions to end of imap.c (Part 1/3)
Moved imap_atom() and imap_sendf() to the end of the file allowing all
utility functions to be grouped together.
2013-04-12 18:24:43 +01:00
Steve Holme
4bbad1dac7 imap: Corrected function description for imap_connect() 2013-04-12 18:14:43 +01:00
Kamil Dudka
ddbda328b3 tests: prevent test206, test1060, and test1061 from failing
... in case runtests.pl is invoked with non-default -b option

Fixes a regression caused by 1e29d275c6.
2013-04-12 14:25:58 +02:00
David Strauss
8ffbeeda80 libcurl-share.3: update what it does and does not share.
Update sharing interface documentation to provide exhaustive list of
what it does and does not share.
2013-04-12 13:35:29 +02:00
Daniel Stenberg
1d1ffaf912 THANKS: remove duplicated names 2013-04-12 12:37:47 +02:00
Daniel Stenberg
e0cff02061 bump: start working towards next release 2013-04-12 11:30:32 +02:00
Daniel Stenberg
7fe95bb0d5 THANKS: added people from the 7.30.0 RELEASE-NOTES 2013-04-12 11:30:12 +02:00
139 changed files with 4765 additions and 1596 deletions

View File

@@ -103,7 +103,7 @@ if test ! -z $SDK32; then
ln -fs ${FRAMEWORK_VERSION}/Resources Resources
ln -fs ${FRAMEWORK_VERSION}/Headers Headers
cd Versions
ln -fs ${FRAMEWORK_VERSION} Current
ln -fs $(basename "${FRAMEWORK_VERSION}") Current
echo Testing for SDK64
if test -d $SDK64_DIR; then

View File

@@ -1,6 +1,6 @@
Curl and libcurl 7.30.0
Curl and libcurl 7.31.0
Public curl releases: 132
Public curl releases: 133
Command line options: 152
curl_easy_setopt() options: 199
Public functions in libcurl: 58
@@ -14,75 +14,58 @@ Curl and libcurl 7.30.0
This release includes the following changes:
o imap: Changed response tag generation to be completely unique
o imap: Added support for SASL-IR extension
o imap: Added support for the list command
o imap: Added support for the append command
o imap: Added custom request parsing
o imap: Added support to the fetch command for UID and SECTION properties
o imap: Added parsing and verification of the UIDVALIDITY mailbox attribute
o darwinssl: Make certificate errors less techy
o imap/pop3/smtp: Added support for the STARTTLS capability
o checksrc: ban use of sprintf, vsprintf, strcat, strncat and gets
o curl_global_init() now accepts the CURL_GLOBAL_ACK_EINTR flag [10]
o Added CURLMOPT_MAX_HOST_CONNECTIONS, CURLMOPT_MAX_TOTAL_CONNECTIONS for
new multi interface connection handling
o Added CURLMOPT_MAX_PIPELINE_LENGTH, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE,
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLMOPT_PIPELINING_SITE_BL and
CURLMOPT_PIPELINING_SERVER_BL for new pipelining control [15]
o darwinssl: add TLS session resumption
o darwinssl: add TLS crypto authentication
o imap/pop3/smtp: Added support for ;auth=<mech> in the URL
o imap/pop3/smtp: Added support for ;auth=<mech> to CURLOPT_USERPWD
o usercertinmem.c: add example showing user cert in memory
o url: Added smtp and pop3 hostnames to the protocol detection list
o imap/pop3/smtp: Added support for enabling the SASL initial response [8]
o curl -E: allow to use ':' in certificate nicknames [10]
This release includes the following bugfixes:
o SECURITY ADVISORY: cookie tailmatching to avoid cross-domain leakage [25]
o darwinssl: Fix build under Leopard
o DONE: consider callback-aborted transfers premature [1]
o ntlm: Fixed memory leaks
o smtp: Fixed an issue when processing EHLO failure responses
o pop3: Fixed incorrect return value from pop3_endofresp()
o pop3: Fixed SASL authentication capability detection
o pop3: Fixed blocking SSL connect when connecting via POP3S
o imap: Fixed memory leak when performing multiple selects
o nss: fix misplaced code enabling non-blocking socket mode
o AddFormData: prevent only directories from being posted [2]
o darwinssl: fix infinite loop if server disconnected abruptly [3]
o metalink: fix improbable crash parsing metalink filename
o show proper host name on failed resolve
o MacOSX-Framework: Make script work in Xcode 4.0 and later
o strlcat: remove function [4]
o darwinssl: Fix send glitchiness with data > 32 or so KB [5]
o polarssl: better 1.1.x and 1.2.x support
o various documentation improvements
o multi: NULL pointer reference when closing an unused multi handle [9]
o SOCKS: fix socks proxy when noproxy matched [7]
o install-sh: updated to support multiple source files as arguments [6]
o PolarSSL: added human readable error strings
o resolver_error: remove wrong error message output
o docs: updates HTML index and general improvements
o curlbuild.h.dist: enhance non-configure GCC ABI detection logic
o sasl: Fixed null pointer reference when decoding empty digest challenge [8]
o easy: do not ignore poll() failures other than EINTR
o darwinssl: disable ECC ciphers under Mountain Lion by default
o CONNECT: count received headers [11]
o build: fixes for VMS
o CONNECT: clear 'rewindaftersend' on success [12]
o HTTP proxy: insert slash in URL if missing [13]
o hiperfifo: updated to use current libevent API [14]
o getinmemory.c: abort the transfer nicely if not enough memory
o improved win32 memorytracking
o corrected proxy header response headers count [16]
o FTP quote operations on re-used connection [17]
o tcpkeepalive on win32 [18]
o tcpkeepalive on Mac OS X [23]
o easy: acknowledge the CURLOPT_MAXCONNECTS option properly [19]
o easy interface: restore default MAXCONNECTS to 5
o win32: don't set SO_SNDBUF for windows vista or later versions [20]
o HTTP: made cookie sort function more deterministic
o winssl: Fixed memory leak if connection was not successful
o FTP: wait on both connections during active STOR state [21]
o connect: treat a failed local bind of an interface as a non-fatal error [22]
o darwinssl: disable insecure ciphers by default
o FTP: handle "rubbish" in front of directory name in 257 responses [24]
o mk-ca-bundle: Fixed lost OpenSSL output with "-t"
o SECURITY VULNERABILITY: curl_easy_unescape() may parse data beyond the end
of the input buffer [26]
o FTP: access files in root dir correctly [1]
o configure: try pthread_create without -lpthread [2]
o FTP: handle a 230 welcome response [3]
o curl-config: don't output static libs when they are disabled
o CURL_CHECK_CA_BUNDLE: don't check for paths when cross-compiling [4]
o Various documentation updates
o getinfo.c: reset timecond when clearing session-info variables [5]
o FILE: prevent an artificial timeout event due to stale speed-check data [6]
o ftp_state_pasv_resp: connect through proxy also when set by env [7]
o sshserver: disable StrictHostKeyChecking
o ftpserver: Fixed imap logout confirmation data
o curl_easy_init: use less mallocs
o smtp: Fixed unknown percentage complete in progress bar
o smtp: Fixed sending of double CRLF caused by first in EOB
o bindlocal: move brace out of #ifdef [9]
o winssl: Fixed invalid memory access during SSL shutdown [11]
o OS X framework: fix invalid symbolic link
o OpenSSL: allow empty server certificate subject [12]
o axtls: prevent memleaks on SSL handshake failures
o cookies: only consider full path matches
o Revert win32 MemoryTracking: wcsdup() _wcsdup() and _tcsdup() [13]
o Curl_cookie_add: handle IPv6 hosts [14]
o ossl_send: SSL_write() returning 0 is an error too
o ossl_recv: SSL_read() returning 0 is an error too
o Digest auth: escape user names with \ or " in them [15]
o curl_formadd.3: fixed wrong "end-marker" syntax [16]
o libcurl-tutorial.3: fix incorrect backslash [17]
o curl_multi_wait: reduce timeout if the multi handle wants to [18]
o tests/Makefile: typo in the perlcheck target [19]
o axtls: honor disabled VERIFYHOST
o OpenSSL: avoid double free in the PKCS12 certificate code [20]
o multi_socket: reduce timeout inaccuracy margin [21]
o digest: support auth-int for empty entity body [22]
o axtls: now done non-blocking
o lib1900: use tutil_tvnow instead of gettimeofday
o curl_easy_perform: avoid busy-looping [23]
o CURLOPT_COOKIELIST: take cookie share lock [24]
o multi_socket: react on socket close immediately [25]
This release includes the following known bugs:
@@ -91,43 +74,43 @@ 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:
Kamil Dudka, Steve Holme, Nick Zitzmann, Patricia Muscalu, Dan Fandrich,
Gisle Vanem, Guenter Knauf, Yang Tse, Oliver Gondža, Aki Koskinen,
Alexander Klauer, Kim Vandry, Willem Sparreboom, Jeremy Huddleston,
Bruno de Carvalho, Rainer Jung, Jeremy Huddleston, Kim Vandry, Jiri Hruska,
Alexander Klauer, Saran Neti, Alessandro Ghedini, Linus Nielsen Feltzing,
Martin Jansen, John E. Malmberg, Tom Grace, Patrick Monnerat,
Zdenek Pavlas, Myk Taylor, Cédric Deltheil, Robert Wruck, Sam Deane,
Clemens Gruber, Marc Hoersken, Tomas Mlcoch, Fredrik Thulin, Steven Gu,
Andrew Kurushin, Christian Hägele, Daniel Theron, Bill Middlecamp,
Richard Michael, Yamada Yasuharu
David Strauss, Kamil Dudka, Steve Holme, Nick Zitzmann, Sam Deane, Duncan,
Anders Havn, Dan Fandrich, Paul Howarth, Dave Reisner, Wouter Van Rooy,
Linus Nielsen Feltzing, Ishan SinghLevett, Alessandro Ghedini,
Ludovico Cavedon, Zdenek Pavlas, Zekun Ni, Lars Johannesen, Marc Hoersken,
Renaud Guillard, John Gardiner Myers, Jared Jennings, Eric Hu,
Yamada Yasuharu, Stefan Neis, Mike Giancola, Eric S. Raymond, Andrii Moiseiev,
Christian Weisgerber, Peter Gal, Aleksey Tulinov, Hang Su, Sergei Nikulov,
Miguel Angel, Nach M. S., Benjamin Gilbert, Erik Johansson, Timo Sirainen,
Guenter Knauf
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=1184
[2] = http://curl.haxx.se/mail/archive-2013-02/0040.html
[3] = http://curl.haxx.se/mail/lib-2013-03/0014.html
[4] = http://curl.haxx.se/bug/view.cgi?id=1192
[5] = http://curl.haxx.se/mail/lib-2013-02/0145.html
[6] = http://curl.haxx.se/bug/view.cgi?id=1195
[7] = http://curl.haxx.se/bug/view.cgi?id=1190
[8] = http://curl.haxx.se/bug/view.cgi?id=1193
[9] = http://curl.haxx.se/bug/view.cgi?id=1194
[10] = http://curl.haxx.se/bug/view.cgi?id=1168
[11] = http://curl.haxx.se/bug/view.cgi?id=1204
[12] = https://groups.google.com/d/msg/msysgit/B31LNftR4BI/KhRTz0iuGmUJ
[13] = http://curl.haxx.se/bug/view.cgi?id=1206
[14] = http://curl.haxx.se/bug/view.cgi?id=1199
[15] = http://daniel.haxx.se/blog/2013/03/26/better-pipelining-in-libcurl-7-30-0/
[16] = http://curl.haxx.se/bug/view.cgi?id=1204
[17] = http://curl.haxx.se/mail/lib-2013-03/0319.html
[18] = http://curl.haxx.se/bug/view.cgi?id=1209
[19] = http://curl.haxx.se/bug/view.cgi?id=1212
[20] = http://curl.haxx.se/bug/view.cgi?id=1188
[21] = http://curl.haxx.se/bug/view.cgi?id=1183
[22] = http://curl.haxx.se/bug/view.cgi?id=1189
[23] = http://curl.haxx.se/bug/view.cgi?id=1214
[24] = http://curl.haxx.se/mail/lib-2013-04/0113.html
[25] = http://curl.haxx.se/docs/adv_20130412.html
[1] = http://curl.haxx.se/mail/lib-2013-04/0142.html
[2] = http://curl.haxx.se/bug/view.cgi?id=1216
[3] = http://curl.haxx.se/mail/lib-2013-02/0102.html
[4] = http://curl.haxx.se/mail/lib-2013-04/0294.html
[5] = http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=705783
[6] = https://bugzilla.redhat.com/906031
[7] = http://curl.haxx.se/bug/view.cgi?id=1218
[8] = http://curl.haxx.se/mail/lib-2012-03/0114.html
[9] = http://curl.haxx.se/mail/lib-2013-05/0000.html
[10] = http://curl.haxx.se/bug/view.cgi?id=1196
[11] = http://curl.haxx.se/bug/view.cgi?id=1219
[12] = http://curl.haxx.se/bug/view.cgi?id=1220
[13] = http://curl.haxx.se/mail/lib-2013-05/0070.html
[14] = http://curl.haxx.se/bug/view.cgi?id=1221
[15] = http://curl.haxx.se/bug/view.cgi?id=1230
[16] = http://curl.haxx.se/bug/view.cgi?id=1233
[17] = http://curl.haxx.se/bug/view.cgi?id=1234
[18] = http://curl.haxx.se/bug/view.cgi?id=1224
[19] = http://curl.haxx.se/bug/view.cgi?id=1239
[20] = http://curl.haxx.se/bug/view.cgi?id=1236
[21] = http://curl.haxx.se/bug/view.cgi?id=1228
[22] = http://curl.haxx.se/bug/view.cgi?id=1235
[23] = http://curl.haxx.se/bug/view.cgi?id=1238
[24] = http://curl.haxx.se/bug/view.cgi?id=1215
[25] = http://curl.haxx.se/bug/view.cgi?id=1248
[26] = http://curl.haxx.se/docs/adv_20130622.html

View File

@@ -2619,8 +2619,10 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
fi
capath="$want_capath"
ca="no"
else
dnl neither of --with-ca-* given
elif test "x$cross_compiling" != "xyes"; then
dnl NOT cross-compiling and...
dnl neither of the --with-ca-* options are provided
dnl first try autodetecting a CA bundle , then a CA path
dnl both autodetections can be skipped by --without-ca-*
ca="no"
@@ -2656,10 +2658,11 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
fi
done
fi
else
dnl no option given and cross-compiling
AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling])
fi
if test "x$ca" != "xno"; then
CURL_CA_BUNDLE='"'$ca'"'
AC_DEFINE_UNQUOTED(CURL_CA_BUNDLE, "$ca", [Location of default ca bundle])

View File

@@ -3158,14 +3158,26 @@ if test "$want_thres" = "yes"; then
AC_CHECK_HEADER(pthread.h,
[ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>])
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -pthread"
AC_CHECK_LIB(pthread, pthread_create,
[ AC_MSG_NOTICE([using POSIX threaded DNS lookup])
AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup])
USE_THREADS_POSIX=1
curl_res_msg="threaded"
],
[ CFLAGS="$save_CFLAGS"])
dnl first check for function without lib
AC_CHECK_FUNC(pthread_create, [USE_THREADS_POSIX=1] )
dnl if it wasn't found without lib, search for it in pthread lib
if test "$USE_THREADS_POSIX" != "1"
then
CFLAGS="$CFLAGS -pthread"
AC_CHECK_LIB(pthread, pthread_create,
[USE_THREADS_POSIX=1],
[ CFLAGS="$save_CFLAGS"])
fi
if test "x$USE_THREADS_POSIX" = "x1"
then
AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup])
curl_res_msg="POSIX threaded"
fi
])
fi
@@ -3338,6 +3350,11 @@ dnl yes or no
ENABLE_SHARED="$enable_shared"
AC_SUBST(ENABLE_SHARED)
dnl to let curl-config output the static libraries correctly
ENABLE_STATIC="$enable_static"
AC_SUBST(ENABLE_STATIC)
dnl
dnl For keeping supported features and protocols also in pkg-config file
dnl since it is more cross-compile friendly than curl-config

View File

@@ -155,7 +155,12 @@ while test $# -gt 0; do
;;
--static-libs)
echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
if test "X@ENABLE_STATIC@" != "Xno" ; then
echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
else
echo "curl was built with static libraries disabled" >&2
exit 1
fi
;;
--configure)

View File

@@ -728,7 +728,7 @@ FAQ
When passing on a URL to curl to use, it may respond that the particular
protocol is not supported or disabled. The particular way this error message
is phrased is because curl doesn't make a distinction internally of whether
a particular protocol is not supported (ie never got any code added that
a particular protocol is not supported (i.e. never got any code added that
knows how to speak that protocol) or if it was explicitly disabled. curl can
be built to only support a given set of protocols, and the rest would then
be disabled or not supported.
@@ -1055,11 +1055,11 @@ FAQ
4.19 Why doesn't cURL return an error when the network cable is unplugged?
Unplugging the cable is not an error situation. The TCP/IP protocol stack
Unplugging a cable is not an error situation. The TCP/IP protocol stack
was designed to be fault tolerant, so even though there may be a physical
break somewhere the connection shouldn't be affected, just possibly
delayed. Eventually, the physical break will be fixed or the data will be
re-routed around the physical problem.
re-routed around the physical problem through another path.
In such cases, the TCP/IP stack is responsible for detecting when the
network connection is irrevocably lost. Since with some protocols it is
@@ -1077,6 +1077,12 @@ FAQ
falls too low, and --connect-timeout and --max-time can be used to put an
overall timeout on the connection phase or the entire transfer.
A libcurl-using application running in a known physical environment (e.g.
an embedded device with only a single network connection) may want to act
immediately if its lone network connection goes down. That can be achieved
by having the application monitor the network connection on its own using an
OS-specific mechanism, then signalling libcurl to abort (see also item 5.13).
5. libcurl Issues
@@ -1086,7 +1092,9 @@ FAQ
We have written the libcurl code specifically adjusted for multi-threaded
programs. libcurl will use thread-safe functions instead of non-safe ones if
your system has such.
your system has such. Note that you must never share the same handle in
multiple threads.
If you use a OpenSSL-powered libcurl in a multi-threaded environment, you
need to provide one or two locking functions:

View File

@@ -7,19 +7,19 @@
How cURL Became Like This
In the second half of 1997, Daniel Stenberg came up with the idea to make
Towards the end of 1996, Daniel Stenberg came up with the idea to make
currency-exchange calculations available to Internet Relay Chat (IRC)
users. All the necessary data are published on the Web; he just needed to
automate their retrieval.
Daniel simply adopted an existing command-line open-source tool, httpget, that
Brazilian Rafael Sagula had written. After a few minor adjustments, it did
just what he needed.
Brazilian Rafael Sagula had written and recently release version 0.1 of. After
a few minor adjustments, it did just what he needed. HttpGet 1.0 was released
on April 8th 1997 with brand new HTTP proxy support.
Soon, he found currencies on a GOPHER site, so support for that had to go in,
and not before long FTP download support was added as well. The name of the
project was changed to urlget to better fit what it actually did now, since
the http-only days were already passed.
We soon found and fixed support for getting currencies over GOPHER. Once FTP
download support was added, the name of the project was changed and urlget 2.0
was released in August 1997. The http-only days were already passed.
The project slowly grew bigger. When upload capabilities were added and the
name once again was misleading, a second name change was made and on March 20,

View File

@@ -220,7 +220,7 @@ Win32
adjust as necessary. It is also possible to override these paths with
environment variables, for example:
set ZLIB_PATH=c:\zlib-1.2.7
set ZLIB_PATH=c:\zlib-1.2.8
set OPENSSL_PATH=c:\openssl-0.9.8y
set LIBSSH2_PATH=c:\libssh2-1.4.3
@@ -323,7 +323,7 @@ Win32
documentation on how to compile zlib. Define the ZLIB_PATH environment
variable to the location of zlib.h and zlib.lib, for example:
set ZLIB_PATH=c:\zlib-1.2.7
set ZLIB_PATH=c:\zlib-1.2.8
Then run 'nmake vc-zlib' in curl's root directory.

View File

@@ -3,6 +3,17 @@ 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!
82. When building with the Windows Borland compiler, it fails because the
"tlib" tool doesn't support hyphens (minus signs) in file names and we have
such in the build.
http://curl.haxx.se/bug/view.cgi?id=1222
81. When using -J (with -O), automaticly resumed downloading together with "-C
-" fails. Without -J the same command line works! This happens because the
resume logic is worked out before the target file name (and thus its
pre-transfer size) has been figured out!
http://curl.haxx.se/bug/view.cgi?id=1169
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

View File

@@ -13,9 +13,9 @@ Adam Tkac
Adrian Schuur
Adriano Meirelles
Ajit Dhumale
Aki Koskinen
Akos Pasztory
Alan Pinstein
Albert Chin
Albert Chin-A-Young
Albert Choy
Ale Vesely
@@ -31,6 +31,7 @@ Alex Suykov
Alex Vinnik
Alex aka WindEagle
Alexander Beedie
Alexander Klauer
Alexander Kourakos
Alexander Krasnostavsky
Alexander Lazic
@@ -64,6 +65,7 @@ Andrew Biggs
Andrew Bushnell
Andrew Francis
Andrew Fuller
Andrew Kurushin
Andrew Moise
Andrew Wansink
Andrew de los Reyes
@@ -107,6 +109,7 @@ Bernhard Reutner-Fischer
Bertrand Demiddelaer
Bill Egert
Bill Hoffman
Bill Middlecamp
Bjoern Sikora
Bjorn Augustsson
Bjorn Reese
@@ -153,7 +156,6 @@ Chris Maltby
Chris Mumford
Chris Smowton
Christian Grothoff
Christian Hagele
Christian Hägele
Christian Krause
Christian Kurz
@@ -169,6 +171,7 @@ Christopher Stone
Ciprian Badescu
Claes Jakobsson
Clarence Gardner
Clemens Gruber
Clifford Wolf
Cody Jones
Colin Hogben
@@ -180,10 +183,10 @@ Craig A West
Craig Davison
Craig Markwardt
Cris Bailiff
Cristian Rodriguez
Cristian Rodríguez
Curt Bogmine
Cyrill Osterwalder
Cédric Deltheil
Dag Ekengren
Dagobert Michelsen
Damien Adant
@@ -317,6 +320,7 @@ Fred Machado
Fred New
Fred Noz
Frederic Lepied
Fredrik Thulin
Gabriel Kuri
Gabriel Sjoberg
Garrett Holmstrom
@@ -438,6 +442,7 @@ Jeff Pohlmeyer
Jeff Weber
Jeffrey Pohlmeyer
Jeremy Friesner
Jeremy Huddleston
Jerome Muffat-Meridol
Jerome Vouillon
Jerry Wu
@@ -449,8 +454,8 @@ Jim Drash
Jim Freeman
Jim Hollinger
Jim Meyering
Jiri Jaburek
Jiri Hruska
Jiri Jaburek
Jocelyn Jaubert
Joe Halpin
Joe Malicki
@@ -534,6 +539,7 @@ Kevin Lussier
Kevin Reed
Kevin Roth
Kim Rinnewitz
Kim Vandry
Kimmo Kinnunen
Kjell Ericson
Kjetil Jacobsen
@@ -614,6 +620,7 @@ Martin C. Martin
Martin Drasar
Martin Hager
Martin Hedenfalk
Martin Jansen
Martin Lemke
Martin Skinner
Martin Storsjo
@@ -676,6 +683,7 @@ Mitz Wark
Mohamed Lrhazi
Mohun Biswas
Moonesamy
Myk Taylor
Nathan Coulter
Nathan O'Sullivan
Nathanael Nerode
@@ -709,6 +717,7 @@ Ofer
Olaf Flebbe
Olaf Stueben
Olaf Stüben
Oliver Gondža
Olivier Berger
Oren Tirosh
Ori Avtalion
@@ -720,6 +729,7 @@ Pascal Terjan
Pasha Kuznetsov
Pat Ray
Patrice Guerin
Patricia Muscalu
Patrick Bihan-Faou
Patrick Monnerat
Patrick Scott
@@ -779,6 +789,7 @@ Quinn Slack
Rafa Muyo
Rafael Sagula
Rainer Canavan
Rainer Jung
Rainer Koenig
Rajesh Naganathan
Ralf S. Engelschall
@@ -806,6 +817,7 @@ Richard Bramante
Richard Clayton
Richard Cooper
Richard Gorton
Richard Michael
Richard Prescott
Richard Silverman
Rick Jones
@@ -822,6 +834,7 @@ Robert Iakobashvili
Robert Olson
Robert Schumann
Robert Weaver
Robert Wruck
Robin Cornelius
Robin Johnson
Robin Kay
@@ -846,6 +859,7 @@ Ryan Schmidt
S. Moonesamy
Salvador Dávila
Salvatore Sorrentino
Sam Deane
Sam Listopad
Sampo Kellomaki
Samuel Díaz García
@@ -856,6 +870,7 @@ Sandor Feldi
Santhana Todatry
Saqib Ali
Sara Golemon
Saran Neti
Saul good
Scott Bailey
Scott Barrett
@@ -906,6 +921,7 @@ Steve Oliphant
Steve Roskowski
Steven Bazyl
Steven G. Johnson
Steven Gu
Steven M. Schweda
Steven Parkes
Stoned Elipot
@@ -943,6 +959,7 @@ Todd Ouska
Todd Vierling
Tom Benoist
Tom Donovan
Tom Grace
Tom Lee
Tom Mattison
Tom Moers
@@ -994,9 +1011,11 @@ Wesley Laxton
Wesley Miaw
Wez Furlong
Wilfredo Sanchez
Willem Sparreboom
Wojciech Zwiefka
Wu Yongzheng
Xavier Bouchoux
Yamada Yasuharu
Yang Tse
Yarram Sunil
Yehoshua Hershberg
@@ -1004,6 +1023,7 @@ Yukihiro Kawada
Yuriy Sosov
Yves Arrouye
Yves Lejeune
Zdenek Pavlas
Zmey Petroff
Zvi Har'El
nk

View File

@@ -38,6 +38,7 @@
5.1 Better persistency for HTTP 1.0
5.2 support FF3 sqlite cookie files
5.3 Rearrange request header order
5.4 HTTP2/SPDY
6. TELNET
6.1 ditch stdin
@@ -46,19 +47,18 @@
6.4 send data in chunks
7. SMTP
7.1 Specify the preferred authentication mechanism
7.2 Initial response
7.3 Pipelining
7.4 Graceful base64 decoding failure
7.1 Pipelining
7.2 Graceful base64 decoding failure
7.3 Enhanced capability support
8. POP3
8.1 auth= in URLs
8.2 Initial response
8.3 Graceful base64 decoding failure
8.1 Pipelining
8.2 Graceful base64 decoding failure
8.3 Enhanced capability support
9. IMAP
9.1 auth= in URLs
9.2 Graceful base64 decoding failure
9.1 Graceful base64 decoding failure
9.2 Enhanced capability support
10. LDAP
10.1 SASL based authentication mechanisms
@@ -269,6 +269,25 @@
headers use a default value so only headers that need to be moved have to be
specified.
5.4 HTTP2/SPDY
The first drafts for HTTP2 have been published
(http://tools.ietf.org/html/draft-ietf-httpbis-http2-03) and is so far based
on SPDY (http://www.chromium.org/spdy) designs and experiences. Chances are
it will end up in that style. Chrome and Firefox already support SPDY and
lots of web services do.
It would make sense to implement SPDY support now and later transition into
or add HTTP2 support as well.
We should base or HTTP2/SPDY work on a 3rd party library for the protocol
fiddling. The Spindy library (http://spindly.haxx.se/) was an attempt to make
such a library with an API suitable for use by libcurl but that effort has
more or less stalled. spdylay (https://github.com/tatsuhiro-t/spdylay) may
be a better option, either used directly or wrapped with a more spindly-like
API.
6. TELNET
6.1 ditch stdin
@@ -295,65 +314,54 @@ to provide the data to send.
7. SMTP
7.1 Specify the preferred authentication mechanism
Add the ability to specify the preferred authentication mechanism or a list
of mechanisms that should be used. Not only that, but the order that is
returned by the server during the EHLO response should be honored by curl.
7.2 Initial response
Add the ability for the user to specify whether the initial response is
included in the AUTH command. Some email servers, such as Microsoft
Exchange, can work with either whilst others need to have the initial
response sent separately:
http://curl.haxx.se/mail/lib-2012-03/0114.html
7.3 Pipelining
7.1 Pipelining
Add support for pipelining emails.
7.4 Graceful base64 decoding failure
7.2 Graceful base64 decoding failure
Rather than shutting down the session and returning an error when the
decoding of a base64 encoded authentication response fails, we should
gracefully shutdown the authentication process by sending a * response to the
server as per RFC4954.
7.3 Enhanced capability support
Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the EHLO command.
8. POP3
8.1 auth= in URLs
8.1 Pipelining
Being able to specify the preferred authentication mechanism in the URL as
per RFC2384.
Add support for pipelining commands.
8.2 Initial response
Add the ability for the user to specify whether the initial response is
included in the AUTH command as per RFC5034.
8.3 Graceful base64 decoding failure
8.2 Graceful base64 decoding failure
Rather than shutting down the session and returning an error when the
decoding of a base64 encoded authentication response fails, we should
gracefully shutdown the authentication process by sending a * response to the
server as per RFC5034.
8.3 Enhanced capability support
Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the CAPA command.
9. IMAP
9.1 auth= in URLs
Being able to specify the preferred authentication mechanism in the URL as
per RFC5092.
9.2 Graceful base64 decoding failure
9.1 Graceful base64 decoding failure
Rather than shutting down the session and returning an error when the
decoding of a base64 encoded authentication response fails, we should
gracefully shutdown the authentication process by sending a * response to the
server as per RFC3501.
9.2 Enhanced capability support
Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the CAPABILITY command.
10. LDAP
10.1 SASL based authentication mechanisms
@@ -429,6 +437,12 @@ to provide the data to send.
keys and certs over DNS using DNSSEC as an alternative to the CA model.
http://www.rfc-editor.org/rfc/rfc6698.txt
An initial patch was posted by Suresh Krishnaswamy on March 7th 2013
(http://curl.haxx.se/mail/lib-2013-03/0075.html) but it was a too simple
approach. See Daniel's comments:
http://curl.haxx.se/mail/lib-2013-03/0103.html . libunbound may be the
correct library to base this development on.
13. GnuTLS
13.1 SSL engine stuff

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
@@ -388,7 +388,12 @@ curl the nickname of the certificate to use within the NSS database defined
by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the
NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be
loaded. If you want to use a file from the current directory, please precede
it with "./" prefix, in order to avoid confusion with a nickname.
it with "./" prefix, in order to avoid confusion with a nickname. If the
nickname contains ":", it needs to be preceded by "\\" so that it is not
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.
If this option is used several times, the last one will be used.
.IP "--engine <name>"
@@ -1272,8 +1277,9 @@ Set this option to zero to not timeout retries. (Added in 7.12.3)
If this option is used several times, the last one will be used.
.IP "-s, --silent"
Silent or quiet mode. Don't show progress meter or error messages. Makes
Curl mute.
Silent or quiet mode. Don't show progress meter or error messages. Makes Curl
mute. It will still output the data you ask for, potentially even to the
terminal/stdout unless you redirect it.
.IP "-S, --show-error"
When used with \fI-s\fP it makes curl show an error message if it fails.
.IP "--ssl"

View File

@@ -43,3 +43,5 @@ simplessl
smtp-multi
smtp-tls
url2file
usercertinmem
xmlstream

View File

@@ -5,7 +5,8 @@ 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 \
usercertinmem
# These examples require external dependencies that may not be commonly
# available on POSIX systems, so don't bother attempting to compile them here.
@@ -13,4 +14,4 @@ COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c \
ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
multi-uv.c
multi-uv.c xmlstream.c

View File

@@ -27,14 +27,14 @@
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-spi-winidn
##
## Hint: you can also set environment vars to control the build, f.e.:
## set ZLIB_PATH=c:/zlib-1.2.7
## set ZLIB_PATH=c:/zlib-1.2.8
## set ZLIB=1
#
###########################################################################
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../../zlib-1.2.7
ZLIB_PATH = ../../../zlib-1.2.8
endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH

View File

@@ -14,7 +14,7 @@ endif
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../../zlib-1.2.7
ZLIB_PATH = ../../../zlib-1.2.8
endif
# Edit the path below to point to the base of your OpenSSL package.

View File

@@ -78,4 +78,5 @@ simplepost.c - HTTP POST
simplessl.c - HTTPS example with certificates many options set
synctime.c - Sync local time by extracting date from remote HTTP servers
url2file.c - download a document and store it in a file
xmlstream.c - Stream-parse a document using the streaming Expat parser
10-at-a-time.c - Download many files simultaneously, 10 at a time.

View File

@@ -54,23 +54,22 @@ int main(void)
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
/* open the files */
headerfile = fopen(headerfilename,"w");
headerfile = fopen(headerfilename,"wb");
if (headerfile == NULL) {
curl_easy_cleanup(curl_handle);
return -1;
}
bodyfile = fopen(bodyfilename,"w");
bodyfile = fopen(bodyfilename,"wb");
if (bodyfile == NULL) {
curl_easy_cleanup(curl_handle);
return -1;
}
/* we want the headers to this file handle */
/* we want the headers be written to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, headerfile);
/*
* Notice here that if you want the actual data sent anywhere else but
* stdout, you should consider using the CURLOPT_WRITEDATA option. */
/* we want the body be written to this file handle instead of stdout */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bodyfile);
/* get it! */
curl_easy_perform(curl_handle);
@@ -78,6 +77,9 @@ int main(void)
/* close the header file */
fclose(headerfile);
/* close the body file */
fclose(bodyfile);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);

View File

@@ -0,0 +1,211 @@
/***************************************************************************
* _ _ ____ _
* 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.
*
***************************************************************************/
/* Example using an in memory PEM user certificate and RSA key to retrieve an
* https page.
* Written by Ishan SinghLevett, based on Theo Borm's cacertinmem.c.
* Note this example does not use a CA certificate, however one should be used
* if you want a properly secure connection
*/
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <curl/curl.h>
#include <stdio.h>
static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
fwrite(ptr,size,nmemb,stream);
return(nmemb*size);
}
static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
{
X509 *cert = NULL;
BIO *bio = NULL;
BIO *kbio = NULL;
RSA *rsa = NULL;
int ret;
const char *mypem = /* www.cacert.org */
"-----BEGIN CERTIFICATE-----\n"\
"MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"\
"IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"\
"IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n"\
"Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n"\
"BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi\n"\
"MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ\n"\
"ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC\n"\
"CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ\n"\
"8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6\n"\
"zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y\n"\
"fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7\n"\
"w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc\n"\
"G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k\n"\
"epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q\n"\
"laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ\n"\
"QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU\n"\
"fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826\n"\
"YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w\n"\
"ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY\n"\
"gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe\n"\
"MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0\n"\
"IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy\n"\
"dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw\n"\
"czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0\n"\
"dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl\n"\
"aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC\n"\
"AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg\n"\
"b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB\n"\
"ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc\n"\
"nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg\n"\
"18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c\n"\
"gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl\n"\
"Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY\n"\
"sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T\n"\
"SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF\n"\
"CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum\n"\
"GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n"\
"zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n"\
"omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\
"-----END CERTIFICATE-----\n";
/*replace the XXX with the actual RSA key*/
const char *mykey =
"-----BEGIN RSA PRIVATE KEY-----\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
"-----END RSA PRIVATE KEY-----\n";
(void)curl; /* avoid warnings */
(void)parm; /* avoid warnings */
/* get a BIO */
bio = BIO_new_mem_buf((char *)mypem, -1);
if (bio == NULL) {
printf("BIO_new_mem_buf failed\n");
}
/* use it to read the PEM formatted certificate from memory into an X509
* structure that SSL can use
*/
cert = PEM_read_bio_X509(bio, NULL, 0, NULL);
if (cert == NULL) {
printf("PEM_read_bio_X509 failed...\n");
}
/*tell SSL to use the X509 certificate*/
ret = SSL_CTX_use_certificate((SSL_CTX*)sslctx, cert);
if (ret != 1) {
printf("Use certificate failed\n");
}
/*create a bio for the RSA key*/
kbio = BIO_new_mem_buf((char *)mykey, -1);
if (kbio == NULL) {
printf("BIO_new_mem_buf failed\n");
}
/*read the key bio into an RSA object*/
rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
if (rsa == NULL) {
printf("Failed to create key bio\n");
}
/*tell SSL to use the RSA key from memory*/
ret = SSL_CTX_use_RSAPrivateKey((SSL_CTX*)sslctx, rsa);
if (ret != 1) {
printf("Use Key failed\n");
}
/* all set to go */
return CURLE_OK ;
}
int main(void)
{
CURL *ch;
CURLcode rv;
rv = curl_global_init(CURL_GLOBAL_ALL);
ch = curl_easy_init();
rv = curl_easy_setopt(ch,CURLOPT_VERBOSE, 0L);
rv = curl_easy_setopt(ch,CURLOPT_HEADER, 0L);
rv = curl_easy_setopt(ch,CURLOPT_NOPROGRESS, 1L);
rv = curl_easy_setopt(ch,CURLOPT_NOSIGNAL, 1L);
rv = curl_easy_setopt(ch,CURLOPT_WRITEFUNCTION, *writefunction);
rv = curl_easy_setopt(ch,CURLOPT_WRITEDATA, stdout);
rv = curl_easy_setopt(ch,CURLOPT_HEADERFUNCTION, *writefunction);
rv = curl_easy_setopt(ch,CURLOPT_WRITEHEADER, stderr);
rv = curl_easy_setopt(ch,CURLOPT_SSLCERTTYPE,"PEM");
/* both VERIFYPEER and VERIFYHOST are set to 0 in this case because there is
no CA certificate*/
rv = curl_easy_setopt(ch,CURLOPT_SSL_VERIFYPEER, 0L);
rv = curl_easy_setopt(ch,CURLOPT_SSL_VERIFYHOST, 0L);
rv = curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
rv = curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM");
/* first try: retrieve page without user certificate and key -> will fail
*/
rv = curl_easy_perform(ch);
if (rv==CURLE_OK) {
printf("*** transfer succeeded ***\n");
}
else {
printf("*** transfer failed ***\n");
}
/* second try: retrieve page using user certificate and key -> will succeed
* load the certificate and key by installing a function doing the necessary
* "modifications" to the SSL CONTEXT just before link init
*/
rv = curl_easy_setopt(ch,CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
rv = curl_easy_perform(ch);
if (rv==CURLE_OK) {
printf("*** transfer succeeded ***\n");
}
else {
printf("*** transfer failed ***\n");
}
curl_easy_cleanup(ch);
curl_global_cleanup();
return rv;
}

158
docs/examples/xmlstream.c Normal file
View File

@@ -0,0 +1,158 @@
/***************************************************************************
* _ _ ____ _
* 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.
*
***************************************************************************/
/* Stream-parse a document using the streaming Expat parser.
* Written by David Strauss
*
* Expat => http://www.libexpat.org/
*
* gcc -Wall -I/usr/local/include xmlstream.c -lcurl -lexpat -o xmlstream
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <expat.h>
#include <curl/curl.h>
struct MemoryStruct {
char *memory;
size_t size;
};
struct ParserStruct {
int ok;
size_t tags;
size_t depth;
struct MemoryStruct characters;
};
static void startElement(void *userData, const XML_Char *name, const XML_Char **atts)
{
struct ParserStruct *state = (struct ParserStruct *) userData;
state->tags++;
state->depth++;
/* Get a clean slate for reading in character data. */
free(state->characters.memory);
state->characters.memory = NULL;
state->characters.size = 0;
}
static void characterDataHandler(void *userData, const XML_Char *s, int len)
{
struct ParserStruct *state = (struct ParserStruct *) userData;
struct MemoryStruct *mem = &state->characters;
mem->memory = realloc(mem->memory, mem->size + len + 1);
if(mem->memory == NULL) {
/* Out of memory. */
fprintf(stderr, "Not enough memory (realloc returned NULL).\n");
state->ok = 0;
return;
}
memcpy(&(mem->memory[mem->size]), s, len);
mem->size += len;
mem->memory[mem->size] = 0;
}
static void endElement(void *userData, const XML_Char *name)
{
struct ParserStruct *state = (struct ParserStruct *) userData;
state->depth--;
printf("%5lu %10lu %s\n", state->depth, state->characters.size, name);
}
static size_t parseStreamCallback(void *contents, size_t length, size_t nmemb, void *userp)
{
XML_Parser parser = (XML_Parser) userp;
size_t real_size = length * nmemb;
struct ParserStruct *state = (struct ParserStruct *) XML_GetUserData(parser);
/* Only parse if we're not already in a failure state. */
if (state->ok && XML_Parse(parser, contents, real_size, 0) == 0) {
int error_code = XML_GetErrorCode(parser);
fprintf(stderr, "Parsing response buffer of length %lu failed with error code %d (%s).\n",
real_size, error_code, XML_ErrorString(error_code));
state->ok = 0;
}
return real_size;
}
int main(void)
{
CURL *curl_handle;
CURLcode res;
XML_Parser parser;
struct ParserStruct state;
/* Initialize the state structure for parsing. */
memset(&state, 0, sizeof(struct ParserStruct));
state.ok = 1;
/* Initialize a namespace-aware parser. */
parser = XML_ParserCreateNS(NULL, '\0');
XML_SetUserData(parser, &state);
XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, characterDataHandler);
/* Initalize a libcurl handle. */
curl_global_init(CURL_GLOBAL_ALL ^ CURL_GLOBAL_SSL);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.w3schools.com/xml/simple.xml");
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, parseStreamCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)parser);
printf("Depth Characters Closing Tag\n");
/* Perform the request and any follow-up parsing. */
res = curl_easy_perform(curl_handle);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else if (state.ok) {
/* Expat requires one final call to finalize parsing. */
if (XML_Parse(parser, NULL, 0, 1) == 0) {
int error_code = XML_GetErrorCode(parser);
fprintf(stderr, "Finalizing parsing failed with error code %d (%s).\n",
error_code, XML_ErrorString(error_code));
}
else {
printf(" --------------\n");
printf(" %lu tags total\n", state.tags);
}
}
/* Clean up. */
free(state.characters.memory);
XML_ParserFree(parser);
curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return 0;
}

View File

@@ -342,15 +342,34 @@ argument in the closesocket callback set with
The default value of this parameter is unspecified.
(Option added in 7.21.7)
.IP CURLOPT_PROGRESSFUNCTION
Pass a pointer to a function that matches the following prototype: \fBint
function(void *clientp, double dltotal, double dlnow, double ultotal, double
ulnow); \fP. This function gets called by libcurl instead of its internal
equivalent with a frequent interval during operation (roughly once per second
or sooner) no matter if data is being transferred or not. Unknown/unused
argument values passed to the callback will be set to zero (like if you only
download data, the upload size will remain 0). Returning a non-zero value from
this callback will cause libcurl to abort the transfer and return
\fICURLE_ABORTED_BY_CALLBACK\fP.
Pass a pointer to a function that matches the following prototype:
\fBint function(void *clientp, double dltotal, double dlnow, double ultotal,
double ulnow);\fP
This function gets called by libcurl instead of its internal equivalent with a
frequent interval. While data is being transferred it will be called very
frequently, and during slow periods like when nothing is being transferred it
can slow down to about one call per second.
\fIclientp\fP is the pointer set with \fICURLOPT_PROGRESSDATA\fP, it is not
actually used by libcurl but is only passed along from the application to the
callback.
The callback gets told how much data libcurl will transfer and has
transferred, in number of bytes. \fIdltotal\fP is the total number of bytes
libcurl expects to download in this transfer. \fIdlnow\fP is the number of
bytes downloaded so far. \fIultotal\fP is the total number of bytes libcurl
expects to upload in this transfer. \fIulnow\fP is the number of bytes
uploaded so far.
Unknown/unused argument values passed to the callback will be set to zero
(like if you only download data, the upload size will remain 0). Many times
the callback will be called one or more times first, before it knows the data
sizes so a program must be made to handle that.
Returning a non-zero value from this callback will cause libcurl to abort the
transfer and return \fICURLE_ABORTED_BY_CALLBACK\fP.
If you transfer data with the multi interface, this function will not be
called during periods of idleness unless you call the appropriate libcurl
@@ -620,12 +639,20 @@ scheme://host:port/path
For a greater explanation of the format please see RFC3986.
If the given URL lacks the scheme, or protocol, part ("http://" or "ftp://"
etc), libcurl will attempt to resolve which protocol to use based on the
given host mame. If the protocol is not supported, libcurl will return
(\fICURLE_UNSUPPORTED_PROTOCOL\fP) when you call \fIcurl_easy_perform(3)\fP
or \fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed
information on which protocols are supported.
If the given URL lacks the scheme (such as "http://" or "ftp://" etc) then
libcurl will attempt to resolve the protocol based on one of the following
given host names:
HTTP, FTP, DICT, LDAP, IMAP, POP3 or SMTP
(POP3 and SMTP added in 7.31.0)
Should the protocol, either that specified by the scheme or deduced by libcurl
from the host name, not be supported by libcurl then
(\fICURLE_UNSUPPORTED_PROTOCOL\fP) will be returned from either the
\fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP functions when you
call them. Use \fIcurl_version_info(3)\fP for detailed information of which
protocols are supported by the build of libcurl you are using.
The host part of the URL contains the address of the server that you want to
connect to. This can be the fully qualified domain name of the server, the
@@ -640,17 +667,23 @@ http://192.168.0.1/
http://[2001:1890:1112:1::20]/
It is also possible to specify the user name and password as part of the
host, for some protocols, when connecting to servers that require
authentication.
For example the following types of authentication support this:
It is also possible to specify the user name, password and any supported login
options as part of the host, for the following protocols, when connecting to
servers that require authentication:
http://user:password@www.example.com
ftp://user:password@ftp.example.com
pop3://user:password@mail.example.com
imap://user:password;options@mail.example.com
pop3://user:password;options@mail.example.com
smtp://user:password;options@mail.example.com
At present only IMAP, POP3 and SMTP support login options as part of the host.
For more information about the login options in URL syntax please see RFC2384,
RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
The port is optional and when not specified libcurl will use the default port
based on the determined or specified protocol: 80 for HTTP, 21 for FTP and 25
@@ -1040,8 +1073,8 @@ the full path name to the file you want libcurl to use as .netrc file. If this
option is omitted, and \fICURLOPT_NETRC\fP is set, libcurl will attempt to
find a .netrc file in the current user's home directory. (Added in 7.10.9)
.IP CURLOPT_USERPWD
Pass a char * as parameter, which should be [user name]:[password] to use for
the connection. Use \fICURLOPT_HTTPAUTH\fP to decide the authentication method.
Pass a char * as parameter, pointing to a zero terminated login details string
for the connection. The format of which is: [user name]:[password];[options].
When using NTLM, you can set the domain by prepending it to the user name and
separating the domain and name with a forward (/) or backward slash (\\). Like
@@ -1054,10 +1087,18 @@ and password information to hosts using the initial host name (unless
\fICURLOPT_UNRESTRICTED_AUTH\fP is set), so if libcurl follows locations to
other hosts it will not send the user and password to those. This is enforced
to prevent accidental information leakage.
At present only IMAP, POP3 and SMTP support login options as part of the
details string. For more information about the login options please see
RFC2384, RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
Use \fICURLOPT_HTTPAUTH\fP to specify the authentication method for HTTP based
connections.
.IP CURLOPT_PROXYUSERPWD
Pass a char * as parameter, which should be [user name]:[password] to use for
the connection to the HTTP proxy. Use \fICURLOPT_PROXYAUTH\fP to decide
the authentication method.
the connection to the HTTP proxy.
Use \fICURLOPT_PROXYAUTH\fP to specify the authentication method.
.IP CURLOPT_USERNAME
Pass a char * as parameter, which should be pointing to the zero terminated
user name to use for the transfer.
@@ -1134,7 +1175,7 @@ Microsoft. It uses a challenge-response and hash concept similar to Digest, to
prevent the password from being eavesdropped.
You need to build libcurl with either OpenSSL, GnuTLS or NSS support for this
option to work, or build libcurl on Windows.
option to work, or build libcurl on Windows with SSPI support.
.IP CURLAUTH_NTLM_WB
NTLM delegating to winbind helper. Authentication is performed by a separate
binary application that is executed when needed. The name of the application
@@ -1195,6 +1236,15 @@ actual name and password with the \fICURLOPT_PROXYUSERPWD\fP option. The
bitmask can be constructed by or'ing together the bits listed above for the
\fICURLOPT_HTTPAUTH\fP option. As of this writing, only Basic, Digest and NTLM
work. (Added in 7.10.7)
.IP CURLOPT_SASL_IR
Pass a long. If the value is 1, curl will send the initial response to the
server in the first authentication packet in order to reduce the number of
ping pong requests. Only applicable to supporting SASL authentication
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.
.SH HTTP OPTIONS
.IP CURLOPT_AUTOREFERER
Pass a parameter set to 1 to enable this. When enabled, libcurl will
@@ -1392,10 +1442,12 @@ internally, your added one will be used instead. If you add a header with no
content as in 'Accept:' (no data on the right side of the colon), the
internally used header will get disabled. Thus, using this option you can add
new headers, replace internal headers and remove internal headers. To add a
header with no content, make the content be two quotes: \&"". The headers
included in the linked list must not be CRLF-terminated, because curl adds
CRLF after each header item. Failure to comply with this will result in
strange bugs because the server will most likely ignore part of the headers
header with no content (nothing to the right side of the colon), use the
form 'MyHeader;' (note the ending semicolon).
The headers included in the linked list must not be CRLF-terminated, because
curl adds CRLF after each header item. Failure to comply with this will result
in strange bugs because the server will most likely ignore part of the headers
you specified.
The first line in a request (containing the method, usually a GET or POST) is
@@ -2208,6 +2260,12 @@ 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)
.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
@@ -2216,6 +2274,10 @@ in 7.9.3)
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
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.
.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 - 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
@@ -42,7 +42,7 @@ After the \fIlastitem\fP pointer follow the real arguments.
The pointers \fIfirstitem\fP and \fIlastitem\fP should both be pointing to
NULL in the first call to this function. All list-data will be allocated by
the function itself. You must call \fIcurl_formfree(3)\fP on the
\fIfirstitem\P after the form post has been done to free the resources.
\fIfirstitem\fP after the form post has been done to free the resources.
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.

View File

@@ -74,9 +74,9 @@ The socket \fBcallback\fP function uses a prototype like this
int action, /* see values below */
void *userp, /* private callback pointer */
void *socketp); /* private socket pointer,
\fBNULL\fI if not
\fBNULL\fP if not
previously assigned with
\fIcurl_multi_assign(3)\fP */
\fBcurl_multi_assign(3)\fP */
.fi
The callback MUST return 0.

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
@@ -36,12 +36,17 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
This function polls on all file descriptors used by the curl easy handles
contained in the given multi handle set. It will block until activity is
detected on at least one of the handles or \fItimeout_ms\fP has passed.
Alternatively, if the multi handle has a pending internal timeout that has a
shorter expiry time than \fItimeout_ms\fP, that shorter time will be used
instead to make sure timeout accuracy is reasonably kept.
The calling application may pass additional curl_waitfd structures which are
similar to \fIpoll(2)\fP's pollfd structure to be waited on in the same call.
On completion, if \fInumfds\fP is supplied, it will be populated with the
number of file descriptors on which interesting events occured.
total number of file descriptors on which interesting events occured. This
number can include both libcurl internal descriptors as well as descriptors
provided in \fIextra_fds\fP.
If no extra file descriptors are provided and libcurl has no file descriptor
to offer to wait for, this function will return immediately.

View File

@@ -34,8 +34,10 @@ The share interface was added to enable sharing of data between curl
\&"handles".
.SH "ONE SET OF DATA - MANY TRANSFERS"
You can have multiple easy handles share data between them. Have them update
and use the \fBsame\fP cookie database or DNS cache! This way, each single
transfer will take advantage from data updates made by the other transfer(s).
and use the \fBsame\fP cookie database, DNS cache, TLS session cache! This
way, each single transfer will take advantage from data updates made by the
other transfer(s). The sharing interface, however, does not share active or
persistent connections between different easy handles.
.SH "SHARE OBJECT"
You create a shared object with \fIcurl_share_init(3)\fP. It returns a handle
for a newly created one.

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
@@ -1157,13 +1157,13 @@ and install a CURLOPT_OPENSOCKETFUNCTION callback function in which addresses
are sanitized before use.
.IP "Private Resources"
A user who can control the DNS server of a domain being passed in within
a URL can change the address of the host to a local, private address
which the libcurl application will then use. e.g. The innocuous URL
http://fuzzybunnies.example.com/ could actually resolve to the IP address
of a server behind a firewall, such as 127.0.0.1 or 10.1.2.3
Apps can mitigate against this by setting a CURLOPT_OPENSOCKETFUNCTION
and checking the address before a connection.
A user who can control the DNS server of a domain being passed in within a URL
can change the address of the host to a local, private address which a
server-side libcurl-using application could then use. e.g. the innocuous URL
http://fuzzybunnies.example.com/ could actually resolve to the IP address of a
server behind a firewall, such as 127.0.0.1 or 10.1.2.3. Apps can mitigate
against this by setting a CURLOPT_OPENSOCKETFUNCTION and checking the address
before a connection.
All the malicious scenarios regarding redirected URLs apply just as well
to non-redirected URLs, if the user is allowed to specify an arbitrary URL
@@ -1178,6 +1178,19 @@ IP address and port number for a server local to the app running libcurl
but behind a firewall. Apps can mitigate against this by using the
CURLOPT_FTP_SKIP_PASV_IP option or CURLOPT_FTPPORT.
.IP "IPv6 Addresses"
libcurl will normally handle IPv6 addresses transparently and just as easily
as IPv4 addresses. That means that a sanitizing function that filters out
addressses like 127.0.0.1 isn't sufficient--the equivalent IPv6 addresses ::1,
::, 0:00::0:1, ::127.0.0.1 and ::ffff:7f00:1 supplied somehow by an attacker
would all bypass a naive filter and could allow access to undesired local
resources. IPv6 also has special address blocks like link-local and site-local
that generally shouldn't be accessed by a server-side libcurl-using
application. A poorly-configured firewall installed in a data center,
organization or server may also be configured to limit IPv4 connections but
leave IPv6 connections wide open. In some cases, the CURL_IPRESOLVE_V4 option
can be used to limit resolved addresses to IPv4 only and bypass these issues.
.IP Uploads
When uploading, a redirect can cause a local (or remote) file to be
overwritten. Apps must not allow any unsanitized URL to be passed in
@@ -1250,7 +1263,7 @@ using the Content-disposition: header to generate a file name. An application
could also use CURLINFO_EFFECTIVE_URL to generate a file name from a
server-supplied redirect URL. Special care must be taken to sanitize such
names to avoid the possibility of a malicious server supplying one like
"/etc/passwd", "\autoexec.bat" or even ".bashrc".
"/etc/passwd", "\\autoexec.bat", "prn:" or even ".bashrc".
.IP "Server Certificates"
A secure application should never use the CURLOPT_SSL_VERIFYPEER option to
@@ -1263,10 +1276,15 @@ validated certificates is potentially as insecure as a plain HTTP connection.
On a related issue, be aware that even in situations like when you have
problems with libcurl and ask someone for help, everything you reveal in order
to get best possible help might also impose certain security related
risks. Host names, user names, paths, operating system specifics, etc (not to
risks. Host names, user names, paths, operating system specifics, etc. (not to
mention passwords of course) may in fact be used by intruders to gain
additional information of a potential target.
Be sure to limit access to application logs if they could hold private or
security-related data. Besides the obvious candidates like user names and
passwords, things like URLs, cookies or even file names could also hold
sensitive data.
To avoid this problem, you must of course use your common sense. Often, you
can just edit out the sensitive data or just search/replace your true
information with faked data.
@@ -1347,10 +1365,10 @@ automatically share a lot of the data that otherwise would be kept on a
per-easy handle basis when the easy interface is used.
The DNS cache is shared between handles within a multi handle, making
subsequent name resolvings faster and the connection pool that is kept to
better allow persistent connections and connection re-use is shared. If you're
using the easy interface, you can still share these between specific easy
handles by using the share interface, see \fIlibcurl-share(3)\fP.
subsequent name resolving faster, and the connection pool that is kept to
better allow persistent connections and connection re-use is also shared. If
you're using the easy interface, you can still share these between specific
easy handles by using the share interface, see \fIlibcurl-share(3)\fP.
Some things are never shared automatically, not within multi handles, like for
example cookies so the only way to share that is with the share interface.

View File

@@ -456,6 +456,7 @@ CURLOPT_RTSP_SERVER_CSEQ 7.20.0
CURLOPT_RTSP_SESSION_ID 7.20.0
CURLOPT_RTSP_STREAM_URI 7.20.0
CURLOPT_RTSP_TRANSPORT 7.20.0
CURLOPT_SASL_IR 7.31.0
CURLOPT_SEEKDATA 7.18.0
CURLOPT_SEEKFUNCTION 7.18.0
CURLOPT_SERVER_RESPONSE_TIMEOUT 7.20.0

View File

@@ -1527,9 +1527,12 @@ typedef enum {
/* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
CINIT(SSL_OPTIONS, LONG, 216),
/* set the SMTP auth originator */
/* Set the SMTP auth originator */
CINIT(MAIL_AUTH, OBJECTPOINT, 217),
/* Enable/disable SASL initial response */
CINIT(SASL_IR, LONG, 218),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

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.30.0-DEV"
#define LIBCURL_VERSION "7.31.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 30
#define LIBCURL_VERSION_MINOR 31
#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 0x071e00
#define LIBCURL_VERSION_NUM 0x071f00
/*
* This is the date and time when the full source package was created. The

View File

@@ -83,7 +83,7 @@ CFLAGS += -dWANT_IDN_PROTOTYPES
!ifdef %zlib_root
ZLIB_ROOT = $(%zlib_root)
!else
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.7
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.8
!endif
!ifdef %libssh2_root

View File

@@ -22,7 +22,7 @@ BCCDIR = $(MAKEDIR)\..
# Edit the path below to point to the base of your Zlib sources.
!ifndef ZLIB_PATH
ZLIB_PATH = ..\..\zlib-1.2.7
ZLIB_PATH = ..\..\zlib-1.2.8
!endif
# Edit the path below to point to the base of your OpenSSL package.

View File

@@ -7,14 +7,14 @@
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
##
## Hint: you can also set environment vars to control the build, f.e.:
## set ZLIB_PATH=c:/zlib-1.2.7
## set ZLIB_PATH=c:/zlib-1.2.8
## set ZLIB=1
#
###########################################################################
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.7
ZLIB_PATH = ../../zlib-1.2.8
endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH

View File

@@ -14,7 +14,7 @@ endif
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.7
ZLIB_PATH = ../../zlib-1.2.8
endif
# Edit the path below to point to the base of your OpenSSL package.

View File

@@ -73,7 +73,7 @@ LIBSSH2_PATH = ../../libssh2-1.4.3
!ENDIF
!IFNDEF ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.7
ZLIB_PATH = ../../zlib-1.2.8
!ENDIF
!IFNDEF MACHINE

View File

@@ -35,8 +35,8 @@ USER_CFLAGS:=
# directories where to seek for includes and libraries
OPENSSL_INC := D:/libraries/openssl/openssl-0.9.8y-vxWorks6.3/include
OPENSSL_LIB := D:/libraries/openssl/openssl-0.9.8y-vxWorks6.3
ZLIB_INC := D:/libraries/zlib/zlib-1.2.7-VxWorks6.3/zlib-1.2.7
ZLIB_LIB := D:/libraries/zlib/zlib-1.2.7-VxWorks6.3/binaries/vxworks_3.1_gnu/Debug/lib
ZLIB_INC := D:/libraries/zlib/zlib-1.2.8-VxWorks6.3/zlib-1.2.8
ZLIB_LIB := D:/libraries/zlib/zlib-1.2.8-VxWorks6.3/binaries/vxworks_3.1_gnu/Debug/lib
ARES_INC :=
ARES_LIB :=

View File

@@ -41,26 +41,12 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
#include <unistd.h>
/* The last #include file should be: */
#include "memdebug.h"
#include "hostcheck.h"
/* SSL_read is opied from axTLS compat layer */
static int SSL_read(SSL *ssl, void *buf, int num)
{
uint8_t *read_buf;
int ret;
while((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
if(ret > SSL_OK) {
memcpy(buf, read_buf, ret > num ? num : ret);
}
return ret;
}
/* Global axTLS init, called from Curl_ssl_init() */
int Curl_axtls_init(void)
{
@@ -131,31 +117,40 @@ static CURLcode map_error_to_curl(int axtls_err)
static Curl_recv axtls_recv;
static Curl_send axtls_send;
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic.
*/
CURLcode
Curl_axtls_connect(struct connectdata *conn,
int sockindex)
static void free_ssl_structs(struct ssl_connect_data *connssl)
{
if(connssl->ssl) {
ssl_free (connssl->ssl);
connssl->ssl = NULL;
}
if(connssl->ssl_ctx) {
ssl_ctx_free(connssl->ssl_ctx);
connssl->ssl_ctx = NULL;
}
}
/*
* For both blocking and non-blocking connects, this function sets up the
* ssl context and state. This function is called after the TCP connect
* has completed.
*/
static CURLcode connect_prep(struct connectdata *conn, int sockindex)
{
struct SessionHandle *data = conn->data;
SSL_CTX *ssl_ctx;
SSL *ssl;
SSL *ssl = NULL;
int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
int i, ssl_fcn_return;
const uint8_t *ssl_sessionid;
size_t ssl_idsize;
const char *peer_CN;
uint32_t dns_altname_index;
const char *dns_altname;
int8_t found_subject_alt_names = 0;
int8_t found_subject_alt_name_matching_conn = 0;
/* Assuming users will not compile in custom key/cert to axTLS */
uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER;
/* Assuming users will not compile in custom key/cert to axTLS.
* Also, even for blocking connects, use axTLS non-blocking feature.
*/
uint32_t client_option = SSL_NO_DEFAULT_KEY |
SSL_SERVER_VERIFY_LATER |
SSL_CONNECT_IN_PARTS;
if(conn->ssl[sockindex].state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -184,6 +179,9 @@ Curl_axtls_connect(struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
conn->ssl[sockindex].ssl_ctx = ssl_ctx;
conn->ssl[sockindex].ssl = NULL;
/* Load the trusted CA cert bundle file */
if(data->set.ssl.CAfile) {
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
@@ -191,7 +189,6 @@ Curl_axtls_connect(struct connectdata *conn,
infof(data, "error reading ca cert file %s \n",
data->set.ssl.CAfile);
if(data->set.ssl.verifypeer) {
Curl_axtls_close(conn, sockindex);
return CURLE_SSL_CACERT_BADFILE;
}
}
@@ -225,7 +222,6 @@ Curl_axtls_connect(struct connectdata *conn,
if(cert_types[i] == 0) {
failf(data, "%s is not x509 or pkcs12 format",
data->set.str[STRING_CERT]);
Curl_axtls_close(conn, sockindex);
return CURLE_SSL_CERTPROBLEM;
}
}
@@ -250,7 +246,6 @@ Curl_axtls_connect(struct connectdata *conn,
if(key_types[i] == 0) {
failf(data, "Failure: %s is not a supported key file",
data->set.str[STRING_KEY]);
Curl_axtls_close(conn, sockindex);
return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -271,14 +266,25 @@ Curl_axtls_connect(struct connectdata *conn,
else
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
/* Check to make sure handshake was ok. */
ssl_fcn_return = ssl_handshake_status(ssl);
if(ssl_fcn_return != SSL_OK) {
Curl_axtls_close(conn, sockindex);
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
return map_error_to_curl(ssl_fcn_return);
}
infof (data, "handshake completed successfully\n");
conn->ssl[sockindex].ssl = ssl;
return CURLE_OK;
}
/*
* For both blocking and non-blocking connects, this function finalizes the
* SSL connection.
*/
static CURLcode connect_finish(struct connectdata *conn, int sockindex)
{
struct SessionHandle *data = conn->data;
SSL *ssl = conn->ssl[sockindex].ssl;
const uint8_t *ssl_sessionid;
size_t ssl_idsize;
const char *peer_CN;
uint32_t dns_altname_index;
const char *dns_altname;
int8_t found_subject_alt_names = 0;
int8_t found_subject_alt_name_matching_conn = 0;
/* Here, gtls.c gets the peer certificates and fails out depending on
* settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
@@ -289,7 +295,7 @@ Curl_axtls_connect(struct connectdata *conn,
if(ssl_verify_cert(ssl) != SSL_OK) {
Curl_axtls_close(conn, sockindex);
failf(data, "server cert verify failed");
return CURLE_SSL_CONNECT_ERROR;
return CURLE_PEER_FAILED_VERIFICATION;
}
}
else
@@ -306,7 +312,6 @@ Curl_axtls_connect(struct connectdata *conn,
* this, but a couple fields are available.
*/
/* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
risk of an inifite loop */
for(dns_altname_index = 0; ; dns_altname_index++) {
@@ -326,20 +331,29 @@ Curl_axtls_connect(struct connectdata *conn,
/* RFC2818 checks */
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
/* Break connection ! */
Curl_axtls_close(conn, sockindex);
failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
if(data->set.ssl.verifyhost) {
/* Break connection ! */
Curl_axtls_close(conn, sockindex);
failf(data, "\tsubjectAltName(s) do not match %s\n",
conn->host.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\tsubjectAltName(s) do not match %s\n",
conn->host.dispname);
}
else if(found_subject_alt_names == 0) {
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
CN as a legacy fallback */
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
if(peer_CN == NULL) {
/* Similar behaviour to the OpenSSL interface */
Curl_axtls_close(conn, sockindex);
failf(data, "unable to obtain common name from peer certificate");
return CURLE_PEER_FAILED_VERIFICATION;
if(data->set.ssl.verifyhost) {
Curl_axtls_close(conn, sockindex);
failf(data, "unable to obtain common name from peer certificate");
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "unable to obtain common name from peer certificate");
}
else {
if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
@@ -359,8 +373,6 @@ Curl_axtls_connect(struct connectdata *conn,
/* General housekeeping */
conn->ssl[sockindex].state = ssl_connection_complete;
conn->ssl[sockindex].ssl = ssl;
conn->ssl[sockindex].ssl_ctx = ssl_ctx;
conn->recv[sockindex] = axtls_recv;
conn->send[sockindex] = axtls_send;
@@ -374,6 +386,107 @@ Curl_axtls_connect(struct connectdata *conn,
return CURLE_OK;
}
/*
* Use axTLS's non-blocking connection feature to open an SSL connection.
* This is called after a TCP connection is already established.
*/
CURLcode Curl_axtls_connect_nonblocking(
struct connectdata *conn,
int sockindex,
bool *done)
{
CURLcode conn_step;
int ssl_fcn_return;
*done = FALSE;
/* connectdata is calloc'd and connecting_state is only changed in this
function, so this is safe, as the state is effectively initialized. */
if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
conn_step = connect_prep(conn, sockindex);
if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex);
return conn_step;
}
conn->ssl[sockindex].connecting_state = ssl_connect_2;
}
if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
/* Check to make sure handshake was ok. */
if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
if(ssl_fcn_return < 0) {
Curl_axtls_close(conn, sockindex);
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
return map_error_to_curl(ssl_fcn_return);
}
else {
return CURLE_OK; /* Return control to caller for retries */
}
}
infof (conn->data, "handshake completed successfully\n");
conn->ssl[sockindex].connecting_state = ssl_connect_3;
}
if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
conn_step = connect_finish(conn, sockindex);
if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex);
return conn_step;
}
/* Reset connect state */
conn->ssl[sockindex].connecting_state = ssl_connect_1;
*done = TRUE;
return CURLE_OK;
}
/* Unrecognized state. Things are very bad. */
conn->ssl[sockindex].state = ssl_connection_none;
conn->ssl[sockindex].connecting_state = ssl_connect_1;
/* Return value perhaps not strictly correct, but distinguishes the issue.*/
return CURLE_BAD_FUNCTION_ARGUMENT;
}
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic for a blocking connect.
*/
CURLcode
Curl_axtls_connect(struct connectdata *conn,
int sockindex)
{
CURLcode conn_step = connect_prep(conn, sockindex);
int ssl_fcn_return;
SSL *ssl = conn->ssl[sockindex].ssl;
if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex);
return conn_step;
}
/* Check to make sure handshake was ok. */
while(ssl_handshake_status(ssl) != SSL_OK) {
ssl_fcn_return = ssl_read(ssl, NULL);
if(ssl_fcn_return < 0) {
Curl_axtls_close(conn, sockindex);
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
return map_error_to_curl(ssl_fcn_return);
}
usleep(10000);
}
infof (conn->data, "handshake completed successfully\n");
conn_step = connect_finish(conn, sockindex);
if(conn_step != CURLE_OK) {
Curl_axtls_close(conn, sockindex);
return conn_step;
}
return CURLE_OK;
}
/* return number of sent (non-SSL) bytes */
static ssize_t axtls_send(struct connectdata *conn,
@@ -407,7 +520,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex)
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
infof(conn->data, " Curl_axtls_close\n");
if(connssl->ssl) {
/* line from ssluse.c: (void)SSL_shutdown(connssl->ssl);
axTLS compat layer does nothing for SSL_shutdown */
@@ -415,13 +528,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex)
equivalent. ssl_free and ssl_ctx_free close things.
SSL_set_connect_state(connssl->handle); */
ssl_free (connssl->ssl);
connssl->ssl = NULL;
}
if(connssl->ssl_ctx) {
ssl_ctx_free (connssl->ssl_ctx);
connssl->ssl_ctx = NULL;
}
free_ssl_structs(connssl);
}
/*
@@ -436,8 +543,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct SessionHandle *data = conn->data;
char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
to be at least 120 bytes long. */
uint8_t *buf;
ssize_t nread;
infof(conn->data, " Curl_axtls_shutdown\n");
@@ -457,9 +563,10 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server */
nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf,
sizeof(buf));
notify alert from the server. buf is managed internally by
axTLS and will be released upon calling ssl_free via
free_ssl_structs. */
nread = (ssize_t)ssl_read(connssl->ssl, &buf);
if(nread < SSL_OK) {
failf(data, "close notify alert not received during shutdown");
@@ -476,8 +583,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
retval = -1;
}
ssl_free (connssl->ssl);
connssl->ssl = NULL;
free_ssl_structs(connssl);
}
return retval;
}
@@ -490,26 +596,36 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
{
struct ssl_connect_data *connssl = &conn->ssl[num];
ssize_t ret = 0;
uint8_t *read_buf;
infof(conn->data, " axtls_recv\n");
*err = CURLE_OK;
if(connssl) {
ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize);
/* axTLS isn't terribly generous about error reporting */
/* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
team approves proposed fix. */
if(ret == -3 ) {
ret = ssl_read(connssl->ssl, &read_buf);
if(ret > SSL_OK) {
/* ssl_read returns SSL_OK if there is more data to read, so if it is
larger, then all data has been read already. */
memcpy(buf, read_buf,
(size_t)ret > buffersize ? buffersize : (size_t)ret);
}
else if(ret == SSL_OK) {
/* more data to be read, signal caller to call again */
*err = CURLE_AGAIN;
ret = -1;
}
else if(ret == -3) {
/* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
team approves proposed fix. */
Curl_axtls_close(conn, num);
}
else if(ret < 0) {
failf(conn->data, "axTLS recv error (%d)", (int)ret);
else {
failf(conn->data, "axTLS recv error (%d)", ret);
*err = map_error_to_curl(ret);
return -1;
ret = -1;
}
}
*err = CURLE_OK;
return ret;
}

View File

@@ -30,6 +30,10 @@
int Curl_axtls_init(void);
int Curl_axtls_cleanup(void);
CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_axtls_connect_nonblocking(
struct connectdata *conn,
int sockindex,
bool *done);
/* tell axTLS to close down all open information regarding connections (and
thus session ID caching etc) */
@@ -47,6 +51,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn);
#define curlssl_init Curl_axtls_init
#define curlssl_cleanup Curl_axtls_cleanup
#define curlssl_connect Curl_axtls_connect
#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking
#define curlssl_session_free(x) Curl_axtls_session_free(x)
#define curlssl_close_all Curl_axtls_close_all
#define curlssl_close Curl_axtls_close

View File

@@ -38,8 +38,6 @@
/* The last #include file should be: */
#include "memdebug.h"
#define CONNECTION_HASH_SIZE 97
static void free_bundle_hash_entry(void *freethis)
{
struct connectbundle *b = (struct connectbundle *) freethis;
@@ -47,7 +45,7 @@ static void free_bundle_hash_entry(void *freethis)
Curl_bundle_destroy(b);
}
struct conncache *Curl_conncache_init(void)
struct conncache *Curl_conncache_init(int size)
{
struct conncache *connc;
@@ -55,7 +53,7 @@ struct conncache *Curl_conncache_init(void)
if(!connc)
return NULL;
connc->hash = Curl_hash_alloc(CONNECTION_HASH_SIZE, Curl_hash_str,
connc->hash = Curl_hash_alloc(size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
if(!connc->hash) {

View File

@@ -27,7 +27,7 @@ struct conncache {
size_t num_connections;
};
struct conncache *Curl_conncache_init(void);
struct conncache *Curl_conncache_init(int size);
void Curl_conncache_destroy(struct conncache *connc);

View File

@@ -413,23 +413,22 @@ static CURLcode bindlocal(struct connectdata *conn,
if(af == AF_INET6) {
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
char *scope_ptr = strchr(myhost, '%');
if(scope_ptr) *(scope_ptr++) = 0;
if(scope_ptr)
*(scope_ptr++) = 0;
#endif
if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
si6->sin6_family = AF_INET6;
si6->sin6_port = htons(port);
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
if(scope_ptr) {
/* The "myhost" string either comes from Curl_if2ip or
from Curl_printable_address. The latter returns only
numeric scope IDs and the former returns none at all.
So the scope ID, if present, is known to be numeric */
if(scope_ptr)
/* The "myhost" string either comes from Curl_if2ip or from
Curl_printable_address. The latter returns only numeric scope
IDs and the former returns none at all. So the scope ID, if
present, is known to be numeric */
si6->sin6_scope_id = atoi(scope_ptr);
}
}
#endif
sizeof_sa = sizeof(struct sockaddr_in6);
}
sizeof_sa = sizeof(struct sockaddr_in6);
}
else
#endif
@@ -1240,7 +1239,7 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
* 'conn' can be NULL, beware!
*/
int Curl_closesocket(struct connectdata *conn,
curl_socket_t sock)
curl_socket_t sock)
{
if(conn && conn->fclosesocket) {
if((sock == conn->sock[SECONDARYSOCKET]) &&
@@ -1252,7 +1251,13 @@ int Curl_closesocket(struct connectdata *conn,
else
return conn->fclosesocket(conn->closesocket_client, sock);
}
return sclose(sock);
sclose(sock);
if(conn)
/* tell the multi-socket code about this */
Curl_multi_closed(conn, sock);
return 0;
}
/*

View File

@@ -106,6 +106,8 @@ static void freecookie(struct Cookie *co)
free(co->domain);
if(co->path)
free(co->path);
if(co->spath)
free(co->spath);
if(co->name)
free(co->name);
if(co->value)
@@ -143,6 +145,116 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
return FALSE;
}
/*
* matching cookie path and url path
* RFC6265 5.1.4 Paths and Path-Match
*/
static bool pathmatch(const char* cookie_path, const char* request_uri)
{
size_t cookie_path_len;
size_t uri_path_len;
char* uri_path = NULL;
char* pos;
bool ret = FALSE;
/* cookie_path must not have last '/' separator. ex: /sample */
cookie_path_len = strlen(cookie_path);
if(1 == cookie_path_len) {
/* cookie_path must be '/' */
return TRUE;
}
uri_path = strdup(request_uri);
if(!uri_path)
return FALSE;
pos = strchr(uri_path, '?');
if(pos)
*pos = 0x0;
/* #-fragments are already cut off! */
if(0 == strlen(uri_path) || uri_path[0] != '/') {
free(uri_path);
uri_path = strdup("/");
if(!uri_path)
return FALSE;
}
/* here, RFC6265 5.1.4 says
4. Output the characters of the uri-path from the first character up
to, but not including, the right-most %x2F ("/").
but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
without redirect.
Ignore this algorithm because /hoge is uri path for this case
(uri path is not /).
*/
uri_path_len = strlen(uri_path);
if(uri_path_len < cookie_path_len) {
ret = FALSE;
goto pathmatched;
}
/* not using checkprefix() because matching should be case-sensitive */
if(strncmp(cookie_path, uri_path, cookie_path_len)) {
ret = FALSE;
goto pathmatched;
}
/* The cookie-path and the uri-path are identical. */
if(cookie_path_len == uri_path_len) {
ret = TRUE;
goto pathmatched;
}
/* here, cookie_path_len < url_path_len */
if(uri_path[cookie_path_len] == '/') {
ret = TRUE;
goto pathmatched;
}
ret = FALSE;
pathmatched:
free(uri_path);
return ret;
}
/*
* cookie path sanitize
*/
static char *sanitize_cookie_path(const char *cookie_path)
{
size_t len;
char *new_path = strdup(cookie_path);
if(!new_path)
return NULL;
/* some stupid site sends path attribute with '"'. */
if(new_path[0] == '\"') {
memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path));
}
if(new_path[strlen(new_path) - 1] == '\"') {
new_path[strlen(new_path) - 1] = 0x0;
}
/* RFC6265 5.2.4 The Path Attribute */
if(new_path[0] != '/') {
/* Let cookie-path be the default-path. */
free(new_path);
new_path = strdup("/");
return new_path;
}
/* convert /hoge/ to /hoge */
len = strlen(new_path);
if(1 < len && new_path[len - 1] == '/') {
new_path[len - 1] = 0x0;
}
return new_path;
}
/*
* Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
*/
@@ -184,6 +296,9 @@ static void strstore(char **str, const char *newstr)
*
* Add a single cookie line to the cookie keeping object.
*
* Be aware that sometimes we get an IP-only host name, and that might also be
* a numerical IPv6 address.
*
***************************************************************************/
struct Cookie *
@@ -288,72 +403,39 @@ Curl_cookie_add(struct SessionHandle *data,
badcookie = TRUE; /* out of memory bad */
break;
}
co->spath = sanitize_cookie_path(co->path);
if(!co->spath) {
badcookie = TRUE; /* out of memory bad */
break;
}
}
else if(Curl_raw_equal("domain", name)) {
/* note that this name may or may not have a preceding dot, but
we don't care about that, we treat the names the same anyway */
const char *domptr=whatptr;
const char *nextptr;
int dotcount=1;
/* Count the dots, we need to make sure that there are enough
of them. */
/* Now, we make sure that our host is within the given domain,
or the given domain is not valid and thus cannot be set. */
if('.' == whatptr[0])
/* don't count the initial dot, assume it */
domptr++;
whatptr++; /* ignore preceding dot */
do {
nextptr = strchr(domptr, '.');
if(nextptr) {
if(domptr != nextptr)
dotcount++;
domptr = nextptr+1;
if(!domain || tailmatch(whatptr, domain)) {
const char *tailptr=whatptr;
if(tailptr[0] == '.')
tailptr++;
strstore(&co->domain, tailptr); /* don't prefix w/dots
internally */
if(!co->domain) {
badcookie = TRUE;
break;
}
} while(nextptr);
/* The original Netscape cookie spec defined that this domain name
MUST have three dots (or two if one of the seven holy TLDs),
but it seems that these kinds of cookies are in use "out there"
so we cannot be that strict. I've therefore lowered the check
to not allow less than two dots. */
if(dotcount < 2) {
/* Received and skipped a cookie with a domain using too few
dots. */
badcookie=TRUE; /* mark this as a bad cookie */
infof(data, "skipped cookie with illegal dotcount domain: %s\n",
whatptr);
co->tailmatch=TRUE; /* we always do that if the domain name was
given */
}
else {
/* Now, we make sure that our host is within the given domain,
or the given domain is not valid and thus cannot be set. */
if('.' == whatptr[0])
whatptr++; /* ignore preceding dot */
if(!domain || tailmatch(whatptr, domain)) {
const char *tailptr=whatptr;
if(tailptr[0] == '.')
tailptr++;
strstore(&co->domain, tailptr); /* don't prefix w/dots
internally */
if(!co->domain) {
badcookie = TRUE;
break;
}
co->tailmatch=TRUE; /* we always do that if the domain name was
given */
}
else {
/* we did not get a tailmatch and then the attempted set domain
is not a domain to which the current host belongs. Mark as
bad. */
badcookie=TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
whatptr);
}
/* we did not get a tailmatch and then the attempted set domain
is not a domain to which the current host belongs. Mark as
bad. */
badcookie=TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
whatptr);
}
}
else if(Curl_raw_equal("version", name)) {
@@ -461,6 +543,9 @@ Curl_cookie_add(struct SessionHandle *data,
if(co->path) {
memcpy(co->path, path, pathlen);
co->path[pathlen]=0; /* zero terminate */
co->spath = sanitize_cookie_path(co->path);
if(!co->spath)
badcookie = TRUE; /* out of memory bad */
}
else
badcookie = TRUE;
@@ -512,12 +597,6 @@ Curl_cookie_add(struct SessionHandle *data,
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
/* Here's a quick check to eliminate normal HTTP-headers from this */
if(!firstptr || strchr(firstptr, ':')) {
free(co);
return NULL;
}
/* Now loop through the fields and init the struct we already have
allocated */
for(ptr=firstptr, fields=0; ptr && !badcookie;
@@ -552,12 +631,21 @@ Curl_cookie_add(struct SessionHandle *data,
co->path = strdup(ptr);
if(!co->path)
badcookie = TRUE;
else {
co->spath = sanitize_cookie_path(co->path);
if(!co->spath) {
badcookie = TRUE; /* out of memory bad */
}
}
break;
}
/* this doesn't look like a path, make one up! */
co->path = strdup("/");
if(!co->path)
badcookie = TRUE;
co->spath = strdup("/");
if(!co->spath)
badcookie = TRUE;
fields++; /* add a field and fall down to secure */
/* FALLTHROUGH */
case 3:
@@ -628,14 +716,14 @@ Curl_cookie_add(struct SessionHandle *data,
if(replace_old) {
/* the domains were identical */
if(clist->path && co->path) {
if(Curl_raw_equal(clist->path, co->path)) {
if(clist->spath && co->spath) {
if(Curl_raw_equal(clist->spath, co->spath)) {
replace_old = TRUE;
}
else
replace_old = FALSE;
}
else if(!clist->path && !co->path)
else if(!clist->spath && !co->spath)
replace_old = TRUE;
else
replace_old = FALSE;
@@ -664,6 +752,8 @@ Curl_cookie_add(struct SessionHandle *data,
free(clist->domain);
if(clist->path)
free(clist->path);
if(clist->spath)
free(clist->spath);
if(clist->expirestr)
free(clist->expirestr);
@@ -858,10 +948,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* now check the left part of the path with the cookies path
requirement */
if(!co->path ||
/* not using checkprefix() because matching should be
case-sensitive */
!strncmp(co->path, path, strlen(co->path)) ) {
if(!co->spath || pathmatch(co->spath, path) ) {
/* and now, we know this is a match and we should create an
entry for the return-linked-list */

View File

@@ -29,7 +29,8 @@ struct Cookie {
struct Cookie *next; /* next in the chain */
char *name; /* <this> = value */
char *value; /* name = <this> */
char *path; /* path = <this> */
char *path; /* path = <this> which is in Set-Cookie: */
char *spath; /* sanitized cookie path */
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */

View File

@@ -691,6 +691,101 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
return server_cert_summary;
}
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
static OSStatus CopyIdentityWithLabelOldSchool(char *label,
SecIdentityRef *out_c_a_k)
{
OSStatus status = errSecItemNotFound;
/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
deprecation warnings, so let's not compile this unless it's necessary: */
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
SecKeychainAttributeList attr_list;
SecKeychainAttribute attr;
SecKeychainSearchRef search = NULL;
SecCertificateRef cert = NULL;
/* Set up the attribute list: */
attr_list.count = 1L;
attr_list.attr = &attr;
/* Set up our lone search criterion: */
attr.tag = kSecLabelItemAttr;
attr.data = label;
attr.length = (UInt32)strlen(label);
/* Start searching: */
status = SecKeychainSearchCreateFromAttributes(NULL,
kSecCertificateItemClass,
&attr_list,
&search);
if(status == noErr) {
status = SecKeychainSearchCopyNext(search,
(SecKeychainItemRef *)&cert);
if(status == noErr && cert) {
/* If we found a certificate, does it have a private key? */
status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
CFRelease(cert);
}
}
if(search)
CFRelease(search);
#else
#pragma unused(label, out_c_a_k)
#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 */
return status;
}
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
static OSStatus CopyIdentityWithLabel(char *label,
SecIdentityRef *out_cert_and_key)
{
OSStatus status = errSecItemNotFound;
#if defined(__MAC_10_6) || defined(__IPHONE_2_0)
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard. If it
exists, let's use that to find the certificate. */
if(SecItemCopyMatching != NULL) {
CFTypeRef keys[4];
CFTypeRef values[4];
CFDictionaryRef query_dict;
CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
kCFStringEncodingUTF8);
/* Set up our search criteria and expected results: */
values[0] = kSecClassIdentity; /* we want a certificate and a key */
keys[0] = kSecClass;
values[1] = kCFBooleanTrue; /* we want a reference */
keys[1] = kSecReturnRef;
values[2] = kSecMatchLimitOne; /* one is enough, thanks */
keys[2] = kSecMatchLimit;
/* identity searches need a SecPolicyRef in order to work */
values[3] = SecPolicyCreateSSL(false, label_cf);
keys[3] = kSecMatchPolicy;
query_dict = CFDictionaryCreate(NULL, (const void **)keys,
(const void **)values, 4L,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFRelease(values[3]);
CFRelease(label_cf);
/* Do we have a match? */
status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
CFRelease(query_dict);
}
else {
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
/* On Leopard, fall back to SecKeychainSearch. */
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
}
#elif (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
/* For developers building on Leopard, we have no choice but to fall back. */
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
#endif /* defined(__MAC_10_6) || defined(__IPHONE_2_0) */
return status;
}
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
int sockindex)
{
@@ -704,6 +799,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif
size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
char *ssl_sessionid;
size_t ssl_sessionid_len;
OSStatus err = noErr;
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
int darwinver_maj = 0, darwinver_min = 0;
@@ -839,8 +936,57 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
/* No need to load certificates here. SecureTransport uses the Keychain
* (which is also part of the Security framework) to evaluate trust. */
if(data->set.str[STRING_KEY]) {
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
"Transport. The private key must be in the Keychain.");
}
if(data->set.str[STRING_CERT]) {
SecIdentityRef cert_and_key = NULL;
/* User wants to authenticate with a client cert. Look for it: */
err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
if(err == noErr) {
SecCertificateRef cert = NULL;
CFTypeRef certs_c[1];
CFArrayRef certs;
/* If we found one, print it out: */
err = SecIdentityCopyCertificate(cert_and_key, &cert);
if(err == noErr) {
CFStringRef cert_summary = CopyCertSubject(cert);
char cert_summary_c[128];
if(cert_summary) {
memset(cert_summary_c, 0, 128);
if(CFStringGetCString(cert_summary,
cert_summary_c,
128,
kCFStringEncodingUTF8)) {
infof(data, "Client certificate: %s\n", cert_summary_c);
}
CFRelease(cert_summary);
CFRelease(cert);
}
}
certs_c[0] = cert_and_key;
certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
&kCFTypeArrayCallBacks);
err = SSLSetCertificate(connssl->ssl_ctx, certs);
if(certs)
CFRelease(certs);
if(err != noErr) {
failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
return CURLE_SSL_CERTPROBLEM;
}
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]);
return CURLE_SSL_CERTPROBLEM;
}
}
/* SSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
@@ -990,6 +1136,38 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
Curl_safefree(all_ciphers);
Curl_safefree(allowed_ciphers);
/* Check if there's a cached ID we can/should use here! */
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
&ssl_sessionid_len)) {
/* we got a session id, use it! */
err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
infof(data, "SSL re-using session ID\n");
}
/* If there isn't one, then let's make one up! This has to be done prior
to starting the handshake. */
else {
CURLcode retcode;
ssl_sessionid = malloc(256*sizeof(char));
ssl_sessionid_len = snprintf(ssl_sessionid, 256, "curl:%s:%hu",
conn->host.name, conn->remote_port);
err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
if(err != noErr) {
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
return CURLE_SSL_CONNECT_ERROR;
}
retcode = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
if(retcode!= CURLE_OK) {
failf(data, "failed to store ssl session");
return retcode;
}
}
err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
if(err != noErr) {
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
@@ -1059,6 +1237,20 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
"certificate format");
return CURLE_SSL_CONNECT_ERROR;
/* These are all certificate problems with the client: */
case errSecAuthFailed:
failf(data, "SSL authentication failed");
return CURLE_SSL_CONNECT_ERROR;
case errSSLPeerHandshakeFail:
failf(data, "SSL peer handshake failed, the server most likely "
"requires a client certificate to connect");
return CURLE_SSL_CONNECT_ERROR;
case errSSLPeerUnknownCA:
failf(data, "SSL server rejected the client certificate due to "
"the certificate being signed by an unknown certificate "
"authority");
return CURLE_SSL_CONNECT_ERROR;
/* This error is raised if the server's cert didn't match the server's
host name: */
case errSSLHostNameMismatch:
@@ -1462,6 +1654,17 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
return rc;
}
void Curl_darwinssl_session_free(void *ptr)
{
/* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
cached session ID inside the Security framework. There is a private
function that does this, but I don't want to have to explain to you why I
got your application rejected from the App Store due to the use of a
private API, so the best we can do is free up our own char array that we
created way back in darwinssl_connect_step1... */
Curl_safefree(ptr);
}
size_t Curl_darwinssl_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "SecureTransport");

View File

@@ -37,6 +37,7 @@ void Curl_darwinssl_close_all(struct SessionHandle *data);
/* close a SSL connection */
void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
void Curl_darwinssl_session_free(void *ptr);
size_t Curl_darwinssl_version(char *buffer, size_t size);
int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
int Curl_darwinssl_check_cxn(struct connectdata *conn);
@@ -56,7 +57,7 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
#define curlssl_cleanup() Curl_nop_stmt
#define curlssl_connect Curl_darwinssl_connect
#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
#define curlssl_session_free(x) Curl_nop_stmt
#define curlssl_session_free(x) Curl_darwinssl_session_free(x)
#define curlssl_close_all Curl_darwinssl_close_all
#define curlssl_close Curl_darwinssl_close
#define curlssl_shutdown(x,y) 0

View File

@@ -87,9 +87,6 @@ extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
#ifdef WIN32
extern curl_wcsdup_callback Curl_cwcsdup;
#endif
#ifndef CURLDEBUG
@@ -113,19 +110,6 @@ extern curl_wcsdup_callback Curl_cwcsdup;
#undef free
#define free(ptr) Curl_cfree(ptr)
#ifdef WIN32
# undef wcsdup
# define wcsdup(ptr) Curl_cwcsdup(ptr)
# undef _wcsdup
# define _wcsdup(ptr) Curl_cwcsdup(ptr)
# undef _tcsdup
# ifdef UNICODE
# define _tcsdup(ptr) Curl_cwcsdup(ptr)
# else
# define _tcsdup(ptr) Curl_cstrdup(ptr)
# endif
#endif
#endif /* CURLDEBUG */
#else /* CURLX_NO_MEMORY_CALLBACKS */

View File

@@ -25,13 +25,17 @@
#include "pingpong.h"
/* Authentication mechanism flags */
#define SASL_MECH_LOGIN 0x0001
#define SASL_MECH_PLAIN 0x0002
#define SASL_MECH_CRAM_MD5 0x0004
#define SASL_MECH_DIGEST_MD5 0x0008
#define SASL_MECH_GSSAPI 0x0010
#define SASL_MECH_EXTERNAL 0x0020
#define SASL_MECH_NTLM 0x0040
#define SASL_MECH_LOGIN (1 << 0)
#define SASL_MECH_PLAIN (1 << 1)
#define SASL_MECH_CRAM_MD5 (1 << 2)
#define SASL_MECH_DIGEST_MD5 (1 << 3)
#define SASL_MECH_GSSAPI (1 << 4)
#define SASL_MECH_EXTERNAL (1 << 5)
#define SASL_MECH_NTLM (1 << 6)
/* Authentication mechanism values */
#define SASL_AUTH_NONE 0
#define SASL_AUTH_ANY ~0
/* This is used to generate a base64 encoded PLAIN authentication message */
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,

View File

@@ -534,6 +534,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
return retcode;
}
else {
connssl->cred->cached = TRUE;
infof(data, "schannel: stored credential handle in session cache\n");
}
}
@@ -1063,7 +1064,6 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
*/
struct SessionHandle *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct curl_schannel_cred *cached_cred = NULL;
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
conn->host.name, conn->remote_port);
@@ -1141,17 +1141,11 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
connssl->cred->refcount);
}
/* if the handle refcount is zero, check if we have not cached it */
if(connssl->cred->refcount == 0) {
if(Curl_ssl_getsessionid(conn, (void**)&cached_cred, NULL)) {
cached_cred = NULL;
}
/* if the handle was not cached, it is stale to be freed */
if(connssl->cred != cached_cred) {
infof(data, "schannel: clear credential handle\n");
s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle);
Curl_safefree(connssl->cred);
}
/* if the handle was not cached and the refcount is zero */
if(!connssl->cred->cached && connssl->cred->refcount == 0) {
infof(data, "schannel: clear credential handle\n");
s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle);
Curl_safefree(connssl->cred);
}
}
}
@@ -1177,7 +1171,7 @@ void Curl_schannel_session_free(void *ptr)
{
struct curl_schannel_cred *cred = ptr;
if(cred && cred->refcount == 0) {
if(cred && cred->cached && cred->refcount == 0) {
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
Curl_safefree(cred);
}

View File

@@ -270,7 +270,6 @@
# endif
# endif
# include <tchar.h>
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
#endif
/*
@@ -369,7 +368,9 @@
# include <sys/stat.h>
# undef lseek
# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence)
# undef fstat
# define fstat(fdes,stp) _fstati64(fdes, stp)
# undef stat
# define stat(fname,stp) _stati64(fname, stp)
# define struct_stat struct _stati64
# define LSEEK_ERROR (__int64)-1

View File

@@ -73,6 +73,7 @@
#include "non-ascii.h"
#include "warnless.h"
#include "conncache.h"
#include "multiif.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -197,9 +198,6 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
#ifdef WIN32
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)wcsdup;
#endif
#else
/*
* Symbian OS doesn't support initialization to code in writeable static data.
@@ -231,9 +229,6 @@ CURLcode curl_global_init(long flags)
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)system_strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
#ifdef WIN32
Curl_cwcsdup = (curl_wcsdup_callback)wcsdup;
#endif
if(flags & CURL_GLOBAL_SSL)
if(!Curl_ssl_init()) {
@@ -425,6 +420,9 @@ CURLcode curl_easy_perform(CURL *easy)
bool done = FALSE;
int rc;
struct SessionHandle *data = easy;
int without_fds = 0; /* count number of consecutive returns from
curl_multi_wait() without any filedescriptors */
struct timeval before;
if(!easy)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -437,7 +435,9 @@ CURLcode curl_easy_perform(CURL *easy)
if(data->multi_easy)
multi = data->multi_easy;
else {
multi = curl_multi_init();
/* 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;
@@ -463,6 +463,7 @@ CURLcode curl_easy_perform(CURL *easy)
int still_running;
int ret;
before = curlx_tvnow();
mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
if(mcode == CURLM_OK) {
@@ -471,6 +472,27 @@ CURLcode curl_easy_perform(CURL *easy)
code = CURLE_RECV_ERROR;
break;
}
else if(ret == 0) {
struct timeval after = curlx_tvnow();
/* If it returns without any filedescriptor instantly, we need to
avoid busy-looping during periods where it has nothing particular
to wait for */
if(curlx_tvdiff(after, before) <= 10) {
without_fds++;
if(without_fds > 2) {
int sleep_ms = without_fds * 50;
if(sleep_ms > 1000)
sleep_ms = 1000;
Curl_wait_ms(sleep_ms);
}
}
else
/* it wasn't "instant", restart counter */
without_fds = 0;
}
else
/* got file descriptor, restart counter */
without_fds = 0;
mcode = curl_multi_perform(multi, &still_running);
}

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
@@ -159,7 +159,8 @@ CURLcode Curl_urldecode(struct SessionHandle *data,
while(--alloc > 0) {
in = *string;
if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
char hexstr[3];
char *ptr;

View File

@@ -1951,13 +1951,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_PASV_REPLY;
}
if(data->set.str[STRING_PROXY] && *data->set.str[STRING_PROXY]) {
if(conn->bits.proxy) {
/*
* This is a tunnel through a http proxy and we need to connect to the
* proxy again here.
*
* We don't want to rely on a former host lookup that might've expired
* now, instead we remake the lookup here and now!
* This connection uses a proxy and we need to connect to the proxy again
* here. We don't want to rely on a former host lookup that might've
* expired now, instead we remake the lookup here and now!
*/
rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
if(rc == CURLRESOLV_PENDING)
@@ -2711,7 +2709,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* we have now received a full FTP server response */
switch(ftpc->state) {
case FTP_WAIT220:
if(ftpcode != 220) {
if(ftpcode == 230)
/* 230 User logged in - already! */
return ftp_state_user_resp(conn, ftpcode, ftpc->state);
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
return CURLE_FTP_WEIRD_SERVER_REPLY;
@@ -4316,13 +4317,17 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
}
slash_pos=strrchr(cur_pos, '/');
if(slash_pos || !*cur_pos) {
size_t dirlen = slash_pos-cur_pos;
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs)
return CURLE_OUT_OF_MEMORY;
if(!dirlen)
dirlen++;
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
slash_pos ?
curlx_sztosi(slash_pos-cur_pos) : 1,
slash_pos ? curlx_sztosi(dirlen) : 1,
NULL);
if(!ftpc->dirs[0]) {
freedirs(ftpc);
@@ -4377,6 +4382,15 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
}
else {
cur_pos = slash_pos + 1; /* jump to the rest of the string */
if(!ftpc->dirdepth) {
/* path starts with a slash, add that as a directory */
ftpc->dirs[ftpc->dirdepth] = strdup("/");
if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
failf(data, "no memory");
freedirs(ftpc);
return CURLE_OUT_OF_MEMORY;
}
}
continue;
}

View File

@@ -55,6 +55,7 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
info->httpcode = 0;
info->httpversion=0;
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
info->timecond=0;
if(info->contenttype)
free(info->contenttype);

View File

@@ -267,6 +267,38 @@ static void md5_to_ascii(unsigned char *source, /* 16 bytes */
snprintf((char *)&dest[i*2], 3, "%02x", source[i]);
}
/* Perform quoted-string escaping as described in RFC2616 and its errata */
static char *string_quoted(const char *source)
{
char *dest, *d;
const char *s = source;
size_t n = 1; /* null terminator */
/* Calculate size needed */
while(*s) {
++n;
if(*s == '"' || *s == '\\') {
++n;
}
++s;
}
dest = (char *)malloc(n);
if(dest) {
s = source;
d = dest;
while(*s) {
if(*s == '"' || *s == '\\') {
*d++ = '\\';
}
*d++ = *s++;
}
*d = 0;
}
return dest;
}
CURLcode Curl_output_digest(struct connectdata *conn,
bool proxy,
const unsigned char *request,
@@ -289,6 +321,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
char **allocuserpwd;
size_t userlen;
const char *userp;
char *userp_quoted;
const char *passwdp;
struct auth *authp;
@@ -425,16 +458,20 @@ CURLcode Curl_output_digest(struct connectdata *conn,
else
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
if(d->qop && Curl_raw_equal(d->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment.
TODO: replace md5 of empty string with entity-body for PUT/POST */
unsigned char *md5this2 = (unsigned char *)
aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
free(md5this);
md5this = md5this2;
}
if(!md5this) {
free(ha1);
return CURLE_OUT_OF_MEMORY;
}
if(d->qop && Curl_raw_equal(d->qop, "auth-int")) {
/* We don't support auth-int at the moment. I can't see a easy way to get
entity-body here */
/* TODO: Append H(entity-body)*/
}
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
@@ -468,7 +505,18 @@ CURLcode Curl_output_digest(struct connectdata *conn,
Authorization: Digest username="testuser", realm="testrealm", \
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
Digest parameters are all quoted strings. Username which is provided by
the user will need double quotes and backslashes within it escaped. For
the other fields, this shouldn't be an issue. realm, nonce, and opaque
are copied as is from the server, escapes and all. cnonce is generated
with web-safe characters. uri is already percent encoded. nc is 8 hex
characters. algorithm and qop with standard values only contain web-safe
chracters.
*/
userp_quoted = string_quoted(userp);
if(!*userp_quoted)
return CURLE_OUT_OF_MEMORY;
if(d->qop) {
*allocuserpwd =
@@ -482,7 +530,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
"qop=%s, "
"response=\"%s\"",
proxy?"Proxy-":"",
userp,
userp_quoted,
d->realm,
d->nonce,
uripath, /* this is the PATH part of the URL */
@@ -505,12 +553,13 @@ CURLcode Curl_output_digest(struct connectdata *conn,
"uri=\"%s\", "
"response=\"%s\"",
proxy?"Proxy-":"",
userp,
userp_quoted,
d->realm,
d->nonce,
uripath, /* this is the PATH part of the URL */
request_digest);
}
free(userp_quoted);
if(!*allocuserpwd)
return CURLE_OUT_OF_MEMORY;

View File

@@ -86,8 +86,6 @@
#include "memdebug.h"
/* Local API functions */
static CURLcode imap_parse_url_path(struct connectdata *conn);
static CURLcode imap_parse_custom_request(struct connectdata *conn);
static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
static CURLcode imap_do(struct connectdata *conn, bool *done);
static CURLcode imap_done(struct connectdata *conn, CURLcode status,
@@ -99,6 +97,11 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks);
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode imap_setup_connection(struct connectdata *conn);
static char *imap_atom(const char *str);
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...);
static CURLcode imap_parse_url_options(struct connectdata *conn);
static CURLcode imap_parse_url_path(struct connectdata *conn);
static CURLcode imap_parse_custom_request(struct connectdata *conn);
/*
* IMAP protocol handler.
@@ -213,119 +216,6 @@ static void imap_to_imaps(struct connectdata *conn)
#define imap_to_imaps(x) Curl_nop_stmt
#endif
/***********************************************************************
*
* imap_sendf()
*
* Sends the formated string as an IMAP command to the server.
*
* Designed to never block.
*/
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
char *taggedfmt;
va_list ap;
va_start(ap, fmt);
/* Calculate the next command ID wrapping at 3 digits */
imapc->cmdid = (imapc->cmdid + 1) % 1000;
/* Calculate the tag based on the connection ID and command ID */
snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
'A' + (conn->connection_id % 26), imapc->cmdid);
/* Prefix the format with the tag */
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
if(!taggedfmt)
return CURLE_OUT_OF_MEMORY;
/* Send the data with the tag */
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
Curl_safefree(taggedfmt);
va_end(ap);
return result;
}
/***********************************************************************
*
* imap_atom()
*
* Checks the input string for characters that need escaping and returns an
* atom ready for sending to the server.
*
* The returned string needs to be freed.
*
*/
static char *imap_atom(const char *str)
{
const char *p1;
char *p2;
size_t backsp_count = 0;
size_t quote_count = 0;
bool space_exists = FALSE;
size_t newlen = 0;
char *newstr = NULL;
if(!str)
return NULL;
/* Count any unescapped characters */
p1 = str;
while(*p1) {
if(*p1 == '\\')
backsp_count++;
else if(*p1 == '"')
quote_count++;
else if(*p1 == ' ')
space_exists = TRUE;
p1++;
}
/* Does the input contain any unescapped characters? */
if(!backsp_count && !quote_count && !space_exists)
return strdup(str);
/* Calculate the new string length */
newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0);
/* Allocate the new string */
newstr = (char *) malloc((newlen + 1) * sizeof(char));
if(!newstr)
return NULL;
/* Surround the string in quotes if necessary */
p2 = newstr;
if(space_exists) {
newstr[0] = '"';
newstr[newlen - 1] = '"';
p2++;
}
/* Copy the string, escaping backslash and quote characters along the way */
p1 = str;
while(*p1) {
if(*p1 == '\\' || *p1 == '"') {
*p2 = '\\';
p2++;
}
*p2 = *p1;
p1++;
p2++;
}
/* Terminate the string */
newstr[newlen] = '\0';
return newstr;
}
/***********************************************************************
*
* imap_matchresp()
@@ -635,6 +525,7 @@ static CURLcode imap_perform_login(struct connectdata *conn)
static CURLcode imap_perform_authenticate(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
const char *mech = NULL;
char *initresp = NULL;
@@ -653,12 +544,14 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
/* Calculate the supported authentication mechanism by decreasing order of
security */
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(imapc->authmechs & SASL_MECH_DIGEST_MD5) {
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5";
state1 = IMAP_AUTHENTICATE_DIGESTMD5;
imapc->authused = SASL_MECH_DIGEST_MD5;
}
else if(imapc->authmechs & SASL_MECH_CRAM_MD5) {
else if((imapc->authmechs & SASL_MECH_CRAM_MD5) &&
(imapc->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5";
state1 = IMAP_AUTHENTICATE_CRAMMD5;
imapc->authused = SASL_MECH_CRAM_MD5;
@@ -666,67 +559,69 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
else
#endif
#ifdef USE_NTLM
if(imapc->authmechs & SASL_MECH_NTLM) {
if((imapc->authmechs & SASL_MECH_NTLM) &&
(imapc->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM";
state1 = IMAP_AUTHENTICATE_NTLM;
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
imapc->authused = SASL_MECH_NTLM;
if(imapc->ir_supported)
if(imapc->ir_supported || data->set.sasl_ir)
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
&conn->ntlm,
&initresp, &len);
}
else
#endif
if(imapc->authmechs & SASL_MECH_LOGIN) {
if((imapc->authmechs & SASL_MECH_LOGIN) &&
(imapc->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
state1 = IMAP_AUTHENTICATE_LOGIN;
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
imapc->authused = SASL_MECH_LOGIN;
if(imapc->ir_supported)
if(imapc->ir_supported || data->set.sasl_ir)
result = Curl_sasl_create_login_message(conn->data, conn->user,
&initresp, &len);
}
else if(imapc->authmechs & SASL_MECH_PLAIN) {
else if((imapc->authmechs & SASL_MECH_PLAIN) &&
(imapc->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN";
state1 = IMAP_AUTHENTICATE_PLAIN;
state2 = IMAP_AUTHENTICATE_FINAL;
imapc->authused = SASL_MECH_PLAIN;
if(imapc->ir_supported)
if(imapc->ir_supported || data->set.sasl_ir)
result = Curl_sasl_create_plain_message(conn->data, conn->user,
conn->passwd, &initresp, &len);
}
if(result)
return result;
if(!result) {
if(mech) {
/* Perform SASL based authentication */
if(initresp) {
result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
if(mech) {
/* Perform SASL based authentication */
if(initresp) {
result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
if(!result)
state(conn, state2);
}
else {
result = imap_sendf(conn, "AUTHENTICATE %s", mech);
if(!result)
state(conn, state2);
if(!result)
state(conn, state1);
}
Curl_safefree(initresp);
}
else if(!imapc->login_disabled)
/* Perform clear text authentication */
result = imap_perform_login(conn);
else {
result = imap_sendf(conn, "AUTHENTICATE %s", mech);
if(!result)
state(conn, state1);
/* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
Curl_safefree(initresp);
}
else if(!imapc->login_disabled)
/* Perform clear text authentication */
result = imap_perform_login(conn);
else {
/* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
return result;
@@ -1793,8 +1688,10 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
/***********************************************************************
*
* imap_connect() should do everything that is to be considered a part of
* the connection phase.
* imap_connect()
*
* This function should do everything that is to be considered a part of the
* connection phase.
*
* The variable 'done' points to will be TRUE if the protocol-layer connect
* phase is done when this function returns, or FALSE is not. When called as
@@ -1826,9 +1723,17 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
pp->endofresp = imap_endofresp;
pp->conn = conn;
/* Set the default preferred authentication mechanism */
imapc->prefmech = SASL_AUTH_ANY;
/* Initialise the pingpong layer */
Curl_pp_init(pp);
/* Parse the URL options */
result = imap_parse_url_options(conn);
if(result)
return result;
/* Start off waiting for the server greeting response */
state(conn, IMAP_SERVERGREET);
@@ -2044,6 +1949,218 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
return CURLE_OK;
}
/* 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;
(void)connected;
if(imap->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
return CURLE_OK;
}
/* Called from multi.c while DOing */
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
{
CURLcode result = imap_multi_statemach(conn, dophase_done);
if(result)
DEBUGF(infof(conn->data, "DO phase failed\n"));
else if(*dophase_done) {
result = imap_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
return result;
}
/***********************************************************************
*
* imap_regular_transfer()
*
* The input argument is already checked for validity.
*
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
static CURLcode imap_regular_transfer(struct connectdata *conn,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
struct SessionHandle *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
/* Set the progress data */
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0);
/* Carry out the perform */
result = imap_perform(conn, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
result = imap_dophase_done(conn, connected);
return result;
}
static CURLcode imap_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
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 */
#ifndef CURL_DISABLE_HTTP
if(conn->handler == &Curl_handler_imap)
conn->handler = &Curl_handler_imap_proxy;
else {
#ifdef USE_SSL
conn->handler = &Curl_handler_imaps_proxy;
#else
failf(data, "IMAPS not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#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;
#else
failf(data, "IMAP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
/***********************************************************************
*
* imap_sendf()
*
* Sends the formated string as an IMAP command to the server.
*
* Designed to never block.
*/
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
char *taggedfmt;
va_list ap;
va_start(ap, fmt);
/* Calculate the next command ID wrapping at 3 digits */
imapc->cmdid = (imapc->cmdid + 1) % 1000;
/* Calculate the tag based on the connection ID and command ID */
snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
'A' + (conn->connection_id % 26), imapc->cmdid);
/* Prefix the format with the tag */
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
if(!taggedfmt)
return CURLE_OUT_OF_MEMORY;
/* Send the data with the tag */
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
Curl_safefree(taggedfmt);
va_end(ap);
return result;
}
/***********************************************************************
*
* imap_atom()
*
* Checks the input string for characters that need escaping and returns an
* atom ready for sending to the server.
*
* The returned string needs to be freed.
*
*/
static char *imap_atom(const char *str)
{
const char *p1;
char *p2;
size_t backsp_count = 0;
size_t quote_count = 0;
bool space_exists = FALSE;
size_t newlen = 0;
char *newstr = NULL;
if(!str)
return NULL;
/* Count any unescapped characters */
p1 = str;
while(*p1) {
if(*p1 == '\\')
backsp_count++;
else if(*p1 == '"')
quote_count++;
else if(*p1 == ' ')
space_exists = TRUE;
p1++;
}
/* Does the input contain any unescapped characters? */
if(!backsp_count && !quote_count && !space_exists)
return strdup(str);
/* Calculate the new string length */
newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0);
/* Allocate the new string */
newstr = (char *) malloc((newlen + 1) * sizeof(char));
if(!newstr)
return NULL;
/* Surround the string in quotes if necessary */
p2 = newstr;
if(space_exists) {
newstr[0] = '"';
newstr[newlen - 1] = '"';
p2++;
}
/* Copy the string, escaping backslash and quote characters along the way */
p1 = str;
while(*p1) {
if(*p1 == '\\' || *p1 == '"') {
*p2 = '\\';
p2++;
}
*p2 = *p1;
p1++;
p2++;
}
/* Terminate the string */
newstr[newlen] = '\0';
return newstr;
}
/***********************************************************************
*
* imap_is_bchar()
@@ -2082,6 +2199,52 @@ static bool imap_is_bchar(char ch)
}
}
/***********************************************************************
*
* imap_parse_url_options()
*
* Parse the URL login options.
*/
static CURLcode imap_parse_url_options(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
const char *options = conn->options;
const char *ptr = options;
if(options) {
const char *key = ptr;
while(*ptr && *ptr != '=')
ptr++;
if(strnequal(key, "AUTH", 4)) {
const char *value = ptr + 1;
if(strequal(value, "*"))
imapc->prefmech = SASL_AUTH_ANY;
else if(strequal(value, "LOGIN"))
imapc->prefmech = SASL_MECH_LOGIN;
else if(strequal(value, "PLAIN"))
imapc->prefmech = SASL_MECH_PLAIN;
else if(strequal(value, "CRAM-MD5"))
imapc->prefmech = SASL_MECH_CRAM_MD5;
else if(strequal(value, "DIGEST-MD5"))
imapc->prefmech = SASL_MECH_DIGEST_MD5;
else if(strequal(value, "GSSAPI"))
imapc->prefmech = SASL_MECH_GSSAPI;
else if(strequal(value, "NTLM"))
imapc->prefmech = SASL_MECH_NTLM;
else
imapc->prefmech = SASL_AUTH_NONE;
}
else
result = CURLE_URL_MALFORMAT;
}
return result;
}
/***********************************************************************
*
* imap_parse_url_path()
@@ -2192,6 +2355,12 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
return CURLE_OK;
}
/***********************************************************************
*
* imap_parse_custom_request()
*
* Parse the custom request.
*/
static CURLcode imap_parse_custom_request(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -2223,103 +2392,4 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
return result;
}
/* 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;
(void)connected;
if(imap->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
return CURLE_OK;
}
/* Called from multi.c while DOing */
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
{
CURLcode result = imap_multi_statemach(conn, dophase_done);
if(result)
DEBUGF(infof(conn->data, "DO phase failed\n"));
else if(*dophase_done) {
result = imap_dophase_done(conn, FALSE /* not connected */);
DEBUGF(infof(conn->data, "DO phase is complete\n"));
}
return result;
}
/***********************************************************************
*
* imap_regular_transfer()
*
* The input argument is already checked for validity.
*
* Performs all commands done before a regular transfer between a local and a
* remote host.
*/
static CURLcode imap_regular_transfer(struct connectdata *conn,
bool *dophase_done)
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
struct SessionHandle *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
/* Set the progress data */
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
Curl_pgrsSetUploadSize(data, 0);
Curl_pgrsSetDownloadSize(data, 0);
/* Carry out the perform */
result = imap_perform(conn, &connected, dophase_done);
/* Perform post DO phase operations if necessary */
if(!result && *dophase_done)
result = imap_dophase_done(conn, connected);
return result;
}
static CURLcode imap_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
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 */
#ifndef CURL_DISABLE_HTTP
if(conn->handler == &Curl_handler_imap)
conn->handler = &Curl_handler_imap_proxy;
else {
#ifdef USE_SSL
conn->handler = &Curl_handler_imaps_proxy;
#else
failf(data, "IMAPS not supported!");
return CURLE_UNSUPPORTED_PROTOCOL;
#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;
#else
failf(data, "IMAP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
data->state.path++; /* don't include the initial slash */
return CURLE_OK;
}
#endif /* CURL_DISABLE_IMAP */

View File

@@ -76,6 +76,7 @@ struct imap_conn {
imapstate state; /* Always use imap.c:state() to change state! */
bool ssldone; /* Is connect() over SSL done? */
unsigned int authmechs; /* Accepted authentication mechanisms */
unsigned int prefmech; /* Preferred authentication mechanism */
unsigned int authused; /* Auth mechanism used for the connection */
int cmdid; /* Last used command ID */
char resptag[5]; /* Response tag to wait for */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2012, 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
@@ -239,32 +239,6 @@ char *curl_dostrdup(const char *str, int line, const char *source)
return mem;
}
#ifdef WIN32
wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
{
wchar_t *mem;
size_t wsiz, bsiz;
assert(str != NULL);
if(countcheck("wcsdup", line, source))
return NULL;
wsiz = wcslen(str) + 1;
bsiz = wsiz * sizeof(wchar_t);
mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
if(mem)
memcpy(mem, str, bsiz);
if(source)
curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
source, line, str, bsiz, mem);
return mem;
}
#endif
/* We provide a realloc() that accepts a NULL as pointer, which then
performs a malloc(). In order to work with ares. */
void *curl_dorealloc(void *ptr, size_t wantedsize,

View File

@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2012, 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
@@ -46,11 +46,6 @@ CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
const char *source);
CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
#ifdef WIN32
CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
const char *source);
#endif
CURL_EXTERN void curl_memdebug(const char *logname);
CURL_EXTERN void curl_memlimit(long limit);
CURL_EXTERN void curl_memlog(const char *format, ...);
@@ -89,19 +84,6 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
#ifdef WIN32
# undef wcsdup
# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
# undef _wcsdup
# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
# undef _tcsdup
# ifdef UNICODE
# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
# else
# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
# endif
#endif
#define socket(domain,type,protocol)\
curl_socket(domain,type,protocol,__LINE__,__FILE__)
#undef accept /* for those with accept as a macro */

View File

@@ -58,6 +58,7 @@
#define CURL_SOCKET_HASH_TABLE_SIZE 911
#endif
#define CURL_CONNECTION_HASH_SIZE 97
#define CURL_MULTI_HANDLE 0x000bab1e
@@ -75,6 +76,8 @@ static bool isHandleAtHead(struct SessionHandle *handle,
static CURLMcode add_next_timeout(struct timeval now,
struct Curl_multi *multi,
struct SessionHandle *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
#ifdef DEBUGBUILD
static const char * const statename[]={
@@ -246,9 +249,9 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
* per call."
*
*/
static struct curl_hash *sh_init(void)
static struct curl_hash *sh_init(int hashsize)
{
return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
sh_freeentry);
}
@@ -278,7 +281,8 @@ static void multi_freeamsg(void *a, void *b)
(void)b;
}
CURLM *curl_multi_init(void)
struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
int chashsize) /* connection hash */
{
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
@@ -291,11 +295,11 @@ CURLM *curl_multi_init(void)
if(!multi->hostcache)
goto error;
multi->sockhash = sh_init();
multi->sockhash = sh_init(hashsize);
if(!multi->sockhash)
goto error;
multi->conn_cache = Curl_conncache_init();
multi->conn_cache = Curl_conncache_init(chashsize);
if(!multi->conn_cache)
goto error;
@@ -325,6 +329,13 @@ CURLM *curl_multi_init(void)
return NULL;
}
CURLM *curl_multi_init(void)
{
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
CURL_CONNECTION_HASH_SIZE);
}
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *easy_handle)
{
@@ -801,10 +812,18 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
unsigned int nfds = 0;
unsigned int curlfds;
struct pollfd *ufds = NULL;
long timeout_internal;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
/* If the internally desired timeout is actually shorter than requested from
the outside, then use the shorter time! But only if the internal timer
is actually larger than 0! */
(void)multi_timeout(multi, &timeout_internal);
if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms))
timeout_ms = (int)timeout_internal;
/* Count up how many fds we have from the multi handle */
easy=multi->easy.next;
while(easy != &multi->easy) {
@@ -1520,14 +1539,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else
follow = FOLLOW_RETRY;
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
if(easy->result == CURLE_OK)
easy->result = Curl_follow(data, newurl, follow);
if(CURLE_OK == easy->result) {
multistate(easy, CURLM_STATE_CONNECT);
result = CURLM_CALL_MULTI_PERFORM;
newurl = NULL; /* handed over the memory ownership to
Curl_follow(), make sure we don't free() it
here */
easy->result = Curl_follow(data, newurl, follow);
if(CURLE_OK == easy->result) {
multistate(easy, CURLM_STATE_CONNECT);
result = CURLM_CALL_MULTI_PERFORM;
newurl = NULL; /* handed over the memory ownership to
Curl_follow(), make sure we don't free() it
here */
}
}
}
else {
@@ -2031,6 +2051,39 @@ static void singlesocket(struct Curl_multi *multi,
easy->numsocks = num;
}
/*
* Curl_multi_closed()
*
* Used by the connect code to tell the multi_socket code that one of the
* sockets we were using have just been closed. This function will then
* remove it from the sockethash for this handle to make the multi_socket API
* behave properly, especially for the case when libcurl will create another
* socket again and it gets the same file descriptor number.
*/
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
{
struct Curl_multi *multi = conn->data->multi;
if(multi) {
/* this is set if this connection is part of a handle that is added to
a multi handle, and only then this is necessary */
struct Curl_sh_entry *entry =
Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
if(entry) {
if(multi->socket_cb)
multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
multi->socket_userp,
entry->socketp);
/* now remove it from the socket hash */
sh_delentry(multi->sockhash, s);
}
}
}
/*
* add_next_timeout()
*
@@ -2086,6 +2139,11 @@ static CURLMcode add_next_timeout(struct timeval now,
return CURLM_OK;
}
#ifdef WIN32
#define TIMEOUT_INACCURACY 40000
#else
#define TIMEOUT_INACCURACY 3000
#endif
static CURLMcode multi_socket(struct Curl_multi *multi,
bool checkall,
@@ -2175,8 +2233,25 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
}
}
now.tv_usec += 40000; /* compensate for bad precision timers that might've
triggered too early */
/* Compensate for bad precision timers that might've triggered too early.
This precaution was added in commit 2c72732ebf3da5e as a result of bad
resolution in the windows function use(d).
The problematic case here is when using the multi_socket API and libcurl
has told the application about a timeout, and that timeout is what fires
off a bit early. As we don't have any IDs associated with the timeout we
can't tell which timeout that fired off but we only have the times to use
to check what to do. If it fires off too early, we don't run the correct
actions and we don't tell the application again about the same timeout as
was already first in the queue...
Originally we made the timeouts run 40 milliseconds early on all systems,
but now we have an #ifdef setup to provide a decent precaution inaccuracy
margin.
*/
now.tv_usec += TIMEOUT_INACCURACY;
if(now.tv_usec >= 1000000) {
now.tv_sec++;
now.tv_usec -= 1000000;

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, 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
@@ -22,6 +22,8 @@
*
***************************************************************************/
/*
* Prototypes for library-wide functions provided by multi.c
*/
@@ -30,6 +32,10 @@ void Curl_expire(struct SessionHandle *data, long milli);
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
/* Internal version of curl_multi_init() accepts size parameters for the
socket and connection hashes */
struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16
@@ -77,4 +83,16 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
/*
* Curl_multi_closed()
*
* Used by the connect code to tell the multi_socket code that one of the
* sockets we were using have just been closed. This function will then
* remove it from the sockethash for this handle to make the multi_socket API
* behave properly, especially for the case when libcurl will create another
* socket again and it gets the same file descriptor number.
*/
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
#endif /* HEADER_CURL_MULTIIF_H */

View File

@@ -1482,10 +1482,8 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
int rc;
rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);
ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
PR_INTERVAL_NO_WAIT);
if(rc < 0) {
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
@@ -1513,9 +1511,8 @@ static ssize_t nss_recv(struct connectdata * conn, /* connection data */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
ssize_t nread;
nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, -1);
ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
PR_INTERVAL_NO_WAIT);
if(nread < 0) {
/* failed SSL read */
PRInt32 err = PR_GetError();

View File

@@ -90,8 +90,6 @@
#include "memdebug.h"
/* Local API functions */
static CURLcode pop3_parse_url_path(struct connectdata *conn);
static CURLcode pop3_parse_custom_request(struct connectdata *conn);
static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
static CURLcode pop3_do(struct connectdata *conn, bool *done);
static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
@@ -103,6 +101,9 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks);
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode pop3_setup_connection(struct connectdata *conn);
static CURLcode pop3_parse_url_options(struct connectdata *conn);
static CURLcode pop3_parse_url_path(struct connectdata *conn);
static CURLcode pop3_parse_custom_request(struct connectdata *conn);
/*
* POP3 protocol handler.
@@ -216,10 +217,15 @@ static void pop3_to_pop3s(struct connectdata *conn)
#define pop3_to_pop3s(x) Curl_nop_stmt
#endif
/* Function that checks for an ending POP3 status code at the start of the
given string, but also detects the APOP timestamp from the server greeting
and various capabilities from the CAPA response including the supported
authentication types and allowed SASL mechanisms. */
/***********************************************************************
*
* pop3_endofresp()
*
* Checks for an ending POP3 status code at the start of the given string, but
* also detects the APOP timestamp from the server greeting and various
* capabilities from the CAPA response including the supported authentication
* types and allowed SASL mechanisms.
*/
static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
int *resp)
{
@@ -340,7 +346,12 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE; /* Nothing for us */
}
/* This is the ONLY way to change POP3 state! */
/***********************************************************************
*
* state()
*
* This is the ONLY way to change POP3 state!
*/
static void state(struct connectdata *conn, pop3state newstate)
{
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -377,7 +388,14 @@ static void state(struct connectdata *conn, pop3state newstate)
pop3c->state = newstate;
}
static CURLcode pop3_state_capa(struct connectdata *conn)
/***********************************************************************
*
* pop3_perform_capa()
*
* Sends the CAPA command in order to obtain a list of server side supported
* capabilities.
*/
static CURLcode pop3_perform_capa(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -395,7 +413,13 @@ static CURLcode pop3_state_capa(struct connectdata *conn)
return result;
}
static CURLcode pop3_state_starttls(struct connectdata *conn)
/***********************************************************************
*
* pop3_perform_starttls()
*
* Sends the STLS command to start the upgrade to TLS.
*/
static CURLcode pop3_perform_starttls(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -408,7 +432,13 @@ static CURLcode pop3_state_starttls(struct connectdata *conn)
return result;
}
static CURLcode pop3_state_upgrade_tls(struct connectdata *conn)
/***********************************************************************
*
* pop3_perform_upgrade_tls()
*
* Performs the upgrade to TLS.
*/
static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -422,14 +452,20 @@ static CURLcode pop3_state_upgrade_tls(struct connectdata *conn)
if(pop3c->ssldone) {
pop3_to_pop3s(conn);
result = pop3_state_capa(conn);
result = pop3_perform_capa(conn);
}
}
return result;
}
static CURLcode pop3_state_user(struct connectdata *conn)
/***********************************************************************
*
* pop3_perform_user()
*
* Sends a clear text USER command to authenticate with.
*/
static CURLcode pop3_perform_user(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -451,7 +487,13 @@ static CURLcode pop3_state_user(struct connectdata *conn)
}
#ifndef CURL_DISABLE_CRYPTO_AUTH
static CURLcode pop3_state_apop(struct connectdata *conn)
/***********************************************************************
*
* pop3_perform_apop()
*
* Sends an APOP command to authenticate with.
*/
static CURLcode pop3_perform_apop(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -495,12 +537,26 @@ static CURLcode pop3_state_apop(struct connectdata *conn)
}
#endif
static CURLcode pop3_authenticate(struct connectdata *conn)
/***********************************************************************
*
* pop3_perform_authenticate()
*
* Sends an AUTH command allowing the client to login with the appropriate
* SASL authentication mechanism.
*
* Additionally, the function will perform fallback to APOP and USER commands
* should a common mechanism not be available between the client and server.
*/
static CURLcode pop3_perform_authenticate(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *mech = NULL;
pop3state authstate = POP3_STOP;
char *initresp = NULL;
size_t len = 0;
pop3state state1 = POP3_STOP;
pop3state state2 = POP3_STOP;
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
@@ -514,62 +570,158 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
security */
if(pop3c->authtypes & POP3_TYPE_SASL) {
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(pop3c->authmechs & SASL_MECH_DIGEST_MD5) {
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5";
authstate = POP3_AUTH_DIGESTMD5;
state1 = POP3_AUTH_DIGESTMD5;
pop3c->authused = SASL_MECH_DIGEST_MD5;
}
else if(pop3c->authmechs & SASL_MECH_CRAM_MD5) {
else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
(pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5";
authstate = POP3_AUTH_CRAMMD5;
state1 = POP3_AUTH_CRAMMD5;
pop3c->authused = SASL_MECH_CRAM_MD5;
}
else
#endif
#ifdef USE_NTLM
if(pop3c->authmechs & SASL_MECH_NTLM) {
if((pop3c->authmechs & SASL_MECH_NTLM) &&
(pop3c->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM";
authstate = POP3_AUTH_NTLM;
state1 = POP3_AUTH_NTLM;
state2 = POP3_AUTH_NTLM_TYPE2MSG;
pop3c->authused = SASL_MECH_NTLM;
if(data->set.sasl_ir)
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
&conn->ntlm,
&initresp, &len);
}
else
#endif
if(pop3c->authmechs & SASL_MECH_LOGIN) {
if((pop3c->authmechs & SASL_MECH_LOGIN) &&
(pop3c->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
authstate = POP3_AUTH_LOGIN;
state1 = POP3_AUTH_LOGIN;
state2 = POP3_AUTH_LOGIN_PASSWD;
pop3c->authused = SASL_MECH_LOGIN;
if(data->set.sasl_ir)
result = Curl_sasl_create_login_message(conn->data, conn->user,
&initresp, &len);
}
else if(pop3c->authmechs & SASL_MECH_PLAIN) {
else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
(pop3c->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN";
authstate = POP3_AUTH_PLAIN;
state1 = POP3_AUTH_PLAIN;
state2 = POP3_AUTH_FINAL;
pop3c->authused = SASL_MECH_PLAIN;
if(data->set.sasl_ir)
result = Curl_sasl_create_plain_message(conn->data, conn->user,
conn->passwd, &initresp,
&len);
}
}
if(mech) {
/* Perform SASL based authentication */
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
if(!result) {
if(mech && (pop3c->preftype & POP3_TYPE_SASL)) {
/* Perform SASL based authentication */
if(initresp &&
8 + strlen(mech) + len <= 255) { /* AUTH <mech> ...<crlf> */
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
if(!result)
state(conn, authstate);
}
if(!result)
state(conn, state2);
}
else {
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
if(!result)
state(conn, state1);
}
Curl_safefree(initresp);
}
#ifndef CURL_DISABLE_CRYPTO_AUTH
else if(pop3c->authtypes & POP3_TYPE_APOP)
/* Perform APOP authentication */
result = pop3_state_apop(conn);
else if((pop3c->authtypes & POP3_TYPE_APOP) &&
(pop3c->preftype & POP3_TYPE_APOP))
/* Perform APOP authentication */
result = pop3_perform_apop(conn);
#endif
else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT)
/* Perform clear text authentication */
result = pop3_state_user(conn);
else {
/* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
(pop3c->preftype & POP3_TYPE_CLEARTEXT))
/* Perform clear text authentication */
result = pop3_perform_user(conn);
else {
/* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
}
return result;
}
/***********************************************************************
*
* pop3_perform_command()
*
* Sends a POP3 based command.
*/
static CURLcode pop3_perform_command(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
const char *command = NULL;
/* Calculate the default command */
if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
command = "LIST";
if(pop3->id[0] != '\0')
/* Message specific LIST so skip the BODY transfer */
pop3->transfer = FTPTRANSFER_INFO;
}
else
command = "RETR";
/* Send the command */
if(pop3->id[0] != '\0')
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command), pop3->id);
else
result = Curl_pp_sendf(&conn->proto.pop3c.pp,
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command));
if(!result)
state(conn, POP3_COMMAND);
return result;
}
/***********************************************************************
*
* pop3_perform_quit()
*
* Performs the quit action prior to sclose() be called.
*/
static CURLcode pop3_perform_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
/* Send the QUIT command */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT");
if(!result)
state(conn, POP3_QUIT);
return result;
}
/* For the initial server greeting */
static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
int pop3code,
@@ -582,10 +734,10 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
if(pop3code != '+') {
failf(data, "Got unexpected pop3-server response");
return CURLE_FTP_WEIRD_SERVER_REPLY;
result = CURLE_FTP_WEIRD_SERVER_REPLY;
}
result = pop3_state_capa(conn);
else
result = pop3_perform_capa(conn);
return result;
}
@@ -601,22 +753,22 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
(void)instate; /* no use for this yet */
if(pop3code != '+')
result = pop3_state_user(conn);
result = pop3_perform_user(conn);
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(pop3c->tls_supported)
/* Switch to TLS connection now */
result = pop3_state_starttls(conn);
result = pop3_perform_starttls(conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
result = pop3_authenticate(conn);
result = pop3_perform_authenticate(conn);
else {
failf(data, "STLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
result = pop3_authenticate(conn);
result = pop3_perform_authenticate(conn);
return result;
}
@@ -637,15 +789,15 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
result = pop3_authenticate(conn);
result = pop3_perform_authenticate(conn);
}
else
result = pop3_state_upgrade_tls(conn);
result = pop3_perform_upgrade_tls(conn);
return result;
}
/* For AUTH PLAIN responses */
/* For AUTH PLAIN (without initial response) responses */
static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
@@ -682,7 +834,7 @@ static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
return result;
}
/* For AUTH LOGIN responses */
/* For AUTH LOGIN (without initial response) responses */
static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
@@ -879,7 +1031,7 @@ static CURLcode pop3_state_auth_digest_resp_resp(struct connectdata *conn,
#endif
#ifdef USE_NTLM
/* For AUTH NTLM responses */
/* For AUTH NTLM (without initial response) responses */
static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
@@ -980,6 +1132,7 @@ static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
}
#ifndef CURL_DISABLE_CRYPTO_AUTH
/* For APOP responses */
static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
pop3state instate)
{
@@ -1043,41 +1196,6 @@ static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
return result;
}
/* Start the DO phase for the command */
static CURLcode pop3_command(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3;
const char *command = NULL;
/* Calculate the default command */
if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
command = "LIST";
if(pop3->id[0] != '\0')
/* Message specific LIST so skip the BODY transfer */
pop3->transfer = FTPTRANSFER_INFO;
}
else
command = "RETR";
/* Send the command */
if(pop3->id[0] != '\0')
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command), pop3->id);
else
result = Curl_pp_sendf(&conn->proto.pop3c.pp,
(pop3->custom && pop3->custom[0] != '\0' ?
pop3->custom : command));
if(!result)
state(conn, POP3_COMMAND);
return result;
}
/* For command responses */
static CURLcode pop3_state_command_resp(struct connectdata *conn,
int pop3code,
@@ -1146,7 +1264,7 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
if(pop3c->state == POP3_UPGRADETLS)
return pop3_state_upgrade_tls(conn);
return pop3_perform_upgrade_tls(conn);
/* Flush any data that needs to be sent */
if(pp->sendleft)
@@ -1332,9 +1450,18 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
pp->endofresp = pop3_endofresp;
pp->conn = conn;
/* Set the default preferred authentication type and mechanism */
pop3c->preftype = POP3_TYPE_ANY;
pop3c->prefmech = SASL_AUTH_ANY;
/* Initialise the pingpong layer */
Curl_pp_init(pp);
/* Parse the URL options */
result = pop3_parse_url_options(conn);
if(result)
return result;
/* Start off waiting for the server greeting response */
state(conn, POP3_SERVERGREET);
@@ -1407,7 +1534,7 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
*dophase_done = FALSE; /* not done yet */
/* Start the first command in the DO phase */
result = pop3_command(conn);
result = pop3_perform_command(conn);
if(result)
return result;
@@ -1461,25 +1588,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
return result;
}
/***********************************************************************
*
* pop3_quit()
*
* Performs the quit action prior to sclose() be called.
*/
static CURLcode pop3_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
/* Send the QUIT command */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT");
if(!result)
state(conn, POP3_QUIT);
return result;
}
/***********************************************************************
*
* pop3_disconnect()
@@ -1499,7 +1607,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn,
/* The POP3 session may or may not have been allocated/setup at this
point! */
if(!dead_connection && pop3c->pp.conn)
if(!pop3_quit(conn))
if(!pop3_perform_quit(conn))
(void)pop3_block_statemach(conn); /* ignore errors on QUIT */
/* Disconnect from the server */
@@ -1514,37 +1622,6 @@ static CURLcode pop3_disconnect(struct connectdata *conn,
return CURLE_OK;
}
/***********************************************************************
*
* pop3_parse_url_path()
*
* Parse the URL path into separate path components.
*/
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;
const char *path = data->state.path;
/* URL decode the path for the message ID */
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
}
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;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
if(custom)
result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
return result;
}
/* Call this when the DO phase has completed */
static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
{
@@ -1639,8 +1716,116 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
return CURLE_OK;
}
/* This function scans the body after the end-of-body and writes everything
until the end is found */
/***********************************************************************
*
* pop3_parse_url_options()
*
* Parse the URL login options.
*/
static CURLcode pop3_parse_url_options(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
const char *options = conn->options;
const char *ptr = options;
if(options) {
const char *key = ptr;
while(*ptr && *ptr != '=')
ptr++;
if(strnequal(key, "AUTH", 4)) {
const char *value = ptr + 1;
if(strequal(value, "*")) {
pop3c->preftype = POP3_TYPE_ANY;
pop3c->prefmech = SASL_AUTH_ANY;
}
else if(strequal(value, "+APOP")) {
pop3c->preftype = POP3_TYPE_APOP;
pop3c->prefmech = SASL_AUTH_NONE;
}
else if(strequal(value, "LOGIN")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_LOGIN;
}
else if(strequal(value, "PLAIN")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_PLAIN;
}
else if(strequal(value, "CRAM-MD5")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_CRAM_MD5;
}
else if(strequal(value, "DIGEST-MD5")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_DIGEST_MD5;
}
else if(strequal(value, "GSSAPI")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_GSSAPI;
}
else if(strequal(value, "NTLM")) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_NTLM;
}
else {
pop3c->preftype = POP3_TYPE_NONE;
pop3c->prefmech = SASL_AUTH_NONE;
}
}
else
result = CURLE_URL_MALFORMAT;
}
return result;
}
/***********************************************************************
*
* pop3_parse_url_path()
*
* Parse the URL path into separate path components.
*/
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;
const char *path = data->state.path;
/* URL decode the path for the message ID */
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
}
/***********************************************************************
*
* pop3_parse_custom_request()
*
* Parse the custom request.
*/
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;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
if(custom)
result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
return result;
}
/***********************************************************************
*
* Curl_pop3_write()
*
* This function scans the body after the end-of-body and writes everything
* until the end is found.
*/
CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
{
/* This code could be made into a special function in the handler struct */

View File

@@ -72,8 +72,10 @@ struct pop3_conn {
have been received so far */
size_t strip; /* Number of bytes from the start to ignore as
non-body */
unsigned int authtypes; /* Supported authentication types */
unsigned int authtypes; /* Accepted authentication types */
unsigned int authmechs; /* Accepted SASL authentication mechanisms */
unsigned int preftype; /* Preferred authentication type */
unsigned int prefmech; /* Preferred SASL authentication mechanism */
unsigned int authused; /* SASL auth mechanism used for the connection */
char *apoptimestamp; /* APOP timestamp from the server greeting */
bool tls_supported; /* StartTLS capability supported by server */
@@ -83,9 +85,13 @@ extern const struct Curl_handler Curl_handler_pop3;
extern const struct Curl_handler Curl_handler_pop3s;
/* Authentication type flags */
#define POP3_TYPE_CLEARTEXT 0x0001
#define POP3_TYPE_APOP 0x0002
#define POP3_TYPE_SASL 0x0004
#define POP3_TYPE_CLEARTEXT (1 << 0)
#define POP3_TYPE_APOP (1 << 1)
#define POP3_TYPE_SASL (1 << 2)
/* Authentication type values */
#define POP3_TYPE_NONE 0
#define POP3_TYPE_ANY ~0
/* This is the 5-bytes End-Of-Body marker for POP3 */
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"

View File

@@ -26,6 +26,7 @@
* RFC4616 PLAIN authentication
* RFC4954 SMTP Authentication
* RFC5321 SMTP protocol
* Draft SMTP URL Interface
*
***************************************************************************/
@@ -99,6 +100,8 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks);
static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode smtp_setup_connection(struct connectdata *conn);
static CURLcode smtp_parse_url_options(struct connectdata *conn);
static CURLcode smtp_parse_url_path(struct connectdata *conn);
/*
* SMTP protocol handler.
@@ -212,9 +215,14 @@ static void smtp_to_smtps(struct connectdata *conn)
#define smtp_to_smtps(x) Curl_nop_stmt
#endif
/* Function that checks for an ending SMTP status code at the start of the
given string, but also detects various capabilities from the EHLO response
including the supported authentication mechanisms. */
/***********************************************************************
*
* pop3_endofresp()
*
* Checks for an ending SMTP status code at the start of the given string, but
* also detects various capabilities from the EHLO response including the
* supported authentication mechanisms.
*/
static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
int *resp)
{
@@ -292,7 +300,12 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
return result;
}
/* This is the ONLY way to change SMTP state! */
/***********************************************************************
*
* state()
*
* This is the ONLY way to change SMTP state!
*/
static void state(struct connectdata *conn, smtpstate newstate)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -330,7 +343,14 @@ static void state(struct connectdata *conn, smtpstate newstate)
smtpc->state = newstate;
}
static CURLcode smtp_state_ehlo(struct connectdata *conn)
/***********************************************************************
*
* smtp_perform_ehlo()
*
* Sends the EHLO command to not only initialise communication with the ESMTP
* server but to also obtain a list of server side supported capabilities.
*/
static CURLcode smtp_perform_ehlo(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -349,7 +369,13 @@ static CURLcode smtp_state_ehlo(struct connectdata *conn)
return result;
}
static CURLcode smtp_state_helo(struct connectdata *conn)
/***********************************************************************
*
* smtp_perform_helo()
*
* Sends the HELO command to initialise communication with the SMTP server.
*/
static CURLcode smtp_perform_helo(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -366,7 +392,13 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
return result;
}
static CURLcode smtp_state_starttls(struct connectdata *conn)
/***********************************************************************
*
* smtp_perform_starttls()
*
* Sends the STLS command to start the upgrade to TLS.
*/
static CURLcode smtp_perform_starttls(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
@@ -379,7 +411,13 @@ static CURLcode smtp_state_starttls(struct connectdata *conn)
return result;
}
static CURLcode smtp_state_upgrade_tls(struct connectdata *conn)
/***********************************************************************
*
* smtp_perform_upgrade_tls()
*
* Performs the upgrade to TLS.
*/
static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -393,16 +431,24 @@ static CURLcode smtp_state_upgrade_tls(struct connectdata *conn)
if(smtpc->ssldone) {
smtp_to_smtps(conn);
result = smtp_state_ehlo(conn);
result = smtp_perform_ehlo(conn);
}
}
return result;
}
static CURLcode smtp_authenticate(struct connectdata *conn)
/***********************************************************************
*
* smtp_perform_authenticate()
*
* Sends an AUTH command allowing the client to login with the appropriate
* SASL authentication mechanism.
*/
static CURLcode smtp_perform_authenticate(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *mech = NULL;
char *initresp = NULL;
@@ -421,12 +467,14 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
/* Calculate the supported authentication mechanism, by decreasing order of
security, as well as the initial response where appropriate */
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(smtpc->authmechs & SASL_MECH_DIGEST_MD5) {
if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) &&
(smtpc->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5";
state1 = SMTP_AUTH_DIGESTMD5;
smtpc->authused = SASL_MECH_DIGEST_MD5;
}
else if(smtpc->authmechs & SASL_MECH_CRAM_MD5) {
else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) &&
(smtpc->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5";
state1 = SMTP_AUTH_CRAMMD5;
smtpc->authused = SASL_MECH_CRAM_MD5;
@@ -434,61 +482,196 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
else
#endif
#ifdef USE_NTLM
if(smtpc->authmechs & SASL_MECH_NTLM) {
if((smtpc->authmechs & SASL_MECH_NTLM) &&
(smtpc->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM";
state1 = SMTP_AUTH_NTLM;
state2 = SMTP_AUTH_NTLM_TYPE2MSG;
smtpc->authused = SASL_MECH_NTLM;
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
&conn->ntlm,
&initresp, &len);
}
if(data->set.sasl_ir)
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
&conn->ntlm,
&initresp, &len);
}
else
#endif
if(smtpc->authmechs & SASL_MECH_LOGIN) {
if((smtpc->authmechs & SASL_MECH_LOGIN) &&
(smtpc->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN";
state1 = SMTP_AUTH_LOGIN;
state2 = SMTP_AUTH_LOGIN_PASSWD;
smtpc->authused = SASL_MECH_LOGIN;
result = Curl_sasl_create_login_message(conn->data, conn->user,
&initresp, &len);
if(data->set.sasl_ir)
result = Curl_sasl_create_login_message(conn->data, conn->user,
&initresp, &len);
}
else if(smtpc->authmechs & SASL_MECH_PLAIN) {
else if((smtpc->authmechs & SASL_MECH_PLAIN) &&
(smtpc->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN";
state1 = SMTP_AUTH_PLAIN;
state2 = SMTP_AUTH_FINAL;
smtpc->authused = SASL_MECH_PLAIN;
result = Curl_sasl_create_plain_message(conn->data, conn->user,
conn->passwd, &initresp, &len);
}
else {
/* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
if(data->set.sasl_ir)
result = Curl_sasl_create_plain_message(conn->data, conn->user,
conn->passwd, &initresp, &len);
}
if(!result) {
/* Perform SASL based authentication */
if(initresp &&
strlen(mech) + len <= 512 - 8) { /* AUTH <mech> ...<crlf> */
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
if(mech) {
/* Perform SASL based authentication */
if(initresp &&
8 + strlen(mech) + len <= 512) { /* AUTH <mech> ...<crlf> */
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
if(!result)
state(conn, state2);
if(!result)
state(conn, state2);
}
else {
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
if(!result)
state(conn, state1);
}
Curl_safefree(initresp);
}
else {
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
if(!result)
state(conn, state1);
/* Other mechanisms not supported */
infof(conn->data, "No known authentication mechanisms supported!\n");
result = CURLE_LOGIN_DENIED;
}
Curl_safefree(initresp);
}
return result;
}
/***********************************************************************
*
* smtp_perform_mail()
*
* Sends an MAIL command to initiate the upload of a message.
*/
static CURLcode smtp_perform_mail(struct connectdata *conn)
{
char *from = NULL;
char *auth = NULL;
char *size = NULL;
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
/* Calculate the FROM parameter */
if(!data->set.str[STRING_MAIL_FROM])
/* Null reverse-path, RFC-5321, sect. 3.6.3 */
from = strdup("<>");
else if(data->set.str[STRING_MAIL_FROM][0] == '<')
from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
else
from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
if(!from)
return CURLE_OUT_OF_MEMORY;
/* Calculate the optional AUTH parameter */
if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) {
if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
else
/* Empty AUTH, RFC-2554, sect. 5 */
auth = strdup("<>");
if(!auth) {
Curl_safefree(from);
return CURLE_OUT_OF_MEMORY;
}
}
/* Calculate the optional SIZE parameter */
if(conn->proto.smtpc.size_supported && conn->data->set.infilesize > 0) {
size = aprintf("%" FORMAT_OFF_T, data->set.infilesize);
if(!size) {
Curl_safefree(from);
Curl_safefree(auth);
return CURLE_OUT_OF_MEMORY;
}
}
/* Send the MAIL command */
if(!auth && !size)
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s", from);
else if(auth && !size)
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s AUTH=%s", from, auth);
else if(auth && size)
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
else
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s SIZE=%s", from, size);
Curl_safefree(from);
Curl_safefree(auth);
Curl_safefree(size);
if(!result)
state(conn, SMTP_MAIL);
return result;
}
/***********************************************************************
*
* smtp_perform_rcpt_to()
*
* Sends a RCPT TO command for a given recipient as part of the message upload
* process.
*/
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;
/* Send the RCPT TO command */
if(smtp->rcpt) {
if(smtp->rcpt->data[0] == '<')
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
smtp->rcpt->data);
else
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
smtp->rcpt->data);
if(!result)
state(conn, SMTP_RCPT);
}
return result;
}
/***********************************************************************
*
* smtp_perform_quit()
*
* Performs the quit action prior to sclose() being called.
*/
static CURLcode smtp_perform_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
/* Send the QUIT command */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
if(!result)
state(conn, SMTP_QUIT);
return result;
}
/* For the initial server greeting */
static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
int smtpcode,
@@ -501,10 +684,10 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
if(smtpcode/100 != 2) {
failf(data, "Got unexpected smtp-server response: %d", smtpcode);
return CURLE_FTP_WEIRD_SERVER_REPLY;
result = CURLE_FTP_WEIRD_SERVER_REPLY;
}
result = smtp_state_ehlo(conn);
else
result = smtp_perform_ehlo(conn);
return result;
}
@@ -525,10 +708,10 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
result = CURLE_USE_SSL_FAILED;
}
else
result = smtp_authenticate(conn);
result = smtp_perform_authenticate(conn);
}
else
result = smtp_state_upgrade_tls(conn);
result = smtp_perform_upgrade_tls(conn);
return result;
}
@@ -546,7 +729,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
if(smtpcode/100 != 2) {
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
!conn->bits.user_passwd)
result = smtp_state_helo(conn);
result = smtp_perform_helo(conn);
else {
failf(data, "Remote access denied: %d", smtpcode);
result = CURLE_REMOTE_ACCESS_DENIED;
@@ -556,17 +739,17 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
result = smtp_state_starttls(conn);
result = smtp_perform_starttls(conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
result = smtp_authenticate(conn);
result = smtp_perform_authenticate(conn);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
result = smtp_authenticate(conn);
result = smtp_perform_authenticate(conn);
return result;
}
@@ -926,99 +1109,6 @@ static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
return result;
}
/* Start the DO phase */
static CURLcode smtp_mail(struct connectdata *conn)
{
char *from = NULL;
char *auth = NULL;
char *size = NULL;
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
/* Calculate the FROM parameter */
if(!data->set.str[STRING_MAIL_FROM])
/* Null reverse-path, RFC-2821, sect. 3.7 */
from = strdup("<>");
else if(data->set.str[STRING_MAIL_FROM][0] == '<')
from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
else
from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
if(!from)
return CURLE_OUT_OF_MEMORY;
/* Calculate the optional AUTH parameter */
if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) {
if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
else
/* Empty AUTH, RFC-2554, sect. 5 */
auth = strdup("<>");
if(!auth) {
Curl_safefree(from);
return CURLE_OUT_OF_MEMORY;
}
}
/* calculate the optional SIZE parameter */
if(conn->proto.smtpc.size_supported && conn->data->set.infilesize > 0) {
size = aprintf("%" FORMAT_OFF_T, data->set.infilesize);
if(!size) {
Curl_safefree(from);
Curl_safefree(auth);
return CURLE_OUT_OF_MEMORY;
}
}
/* Send the MAIL command */
if(!auth && !size)
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s", from);
else if(auth && !size)
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s AUTH=%s", from, auth);
else if(auth && size)
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
else
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
"MAIL FROM:%s SIZE=%s", from, size);
Curl_safefree(from);
Curl_safefree(auth);
Curl_safefree(size);
if(!result)
state(conn, SMTP_MAIL);
return result;
}
static CURLcode smtp_rcpt_to(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
/* Send the RCPT TO command */
if(smtp->rcpt) {
if(smtp->rcpt->data[0] == '<')
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
smtp->rcpt->data);
else
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
smtp->rcpt->data);
if(!result)
state(conn, SMTP_RCPT);
}
return result;
}
/* For MAIL responses */
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
smtpstate instate)
@@ -1037,7 +1127,7 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
else {
smtp->rcpt = data->set.mail_rcpt;
result = smtp_rcpt_to(conn);
result = smtp_perform_rcpt_to(conn);
}
return result;
@@ -1061,7 +1151,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
else {
if(smtp->rcpt) {
smtp->rcpt = smtp->rcpt->next;
result = smtp_rcpt_to(conn);
result = smtp_perform_rcpt_to(conn);
/* If we failed or still are sending RCPT data then return */
if(result || smtp->rcpt)
@@ -1082,6 +1172,8 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
smtpstate instate)
{
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(smtpcode != 354) {
@@ -1089,6 +1181,9 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
return CURLE_SEND_ERROR;
}
/* Set the progress upload size */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
/* SMTP upload */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
@@ -1129,7 +1224,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
if(smtpc->state == SMTP_UPGRADETLS)
return smtp_state_upgrade_tls(conn);
return smtp_perform_upgrade_tls(conn);
/* Flush any data that needs to be sent */
if(pp->sendleft)
@@ -1300,8 +1395,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
const char *path = conn->data->state.path;
char localhost[HOSTNAME_MAX + 1];
*done = FALSE; /* default to not done yet */
@@ -1323,19 +1416,19 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
pp->endofresp = smtp_endofresp;
pp->conn = conn;
/* Set the default preferred authentication mechanism */
smtpc->prefmech = SASL_AUTH_ANY;
/* Initialise the pingpong layer */
Curl_pp_init(pp);
/* Calculate the path if necessary */
if(!*path) {
if(!Curl_gethostname(localhost, sizeof(localhost)))
path = localhost;
else
path = "localhost";
}
/* Parse the URL options */
result = smtp_parse_url_options(conn);
if(result)
return result;
/* URL decode the path and use it as the domain in our EHLO */
result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
/* Parse the URL path */
result = smtp_parse_url_path(conn);
if(result)
return result;
@@ -1362,6 +1455,9 @@ 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 pingpong *pp = &conn->proto.smtpc.pp;
const char *eob;
ssize_t len;
ssize_t bytes_written;
(void)premature;
@@ -1378,25 +1474,27 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
result = status; /* use the already set error code */
}
else if(!data->set.connect_only) {
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct pingpong *pp = &smtpc->pp;
/* Calculate the EOB taking into account any terminating CRLF from the
previous line of the email or the CRLF of the DATA command when there
is "no mail data". RFC-5321, sect. 4.1.1.4. */
eob = SMTP_EOB;
len = SMTP_EOB_LEN;
if(smtp->trailing_crlf || !conn->data->set.infilesize) {
eob += 2;
len -= 2;
}
/* Send the end of block data */
result = Curl_write(conn,
conn->writesockfd, /* socket to send to */
SMTP_EOB, /* buffer pointer */
SMTP_EOB_LEN, /* buffer size */
&bytes_written); /* actually sent away */
result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
if(result)
return result;
if(bytes_written != SMTP_EOB_LEN) {
if(bytes_written != len) {
/* The whole chunk was not sent so keep it around and adjust the
pingpong structure accordingly */
pp->sendthis = strdup(SMTP_EOB);
pp->sendsize = SMTP_EOB_LEN;
pp->sendleft = SMTP_EOB_LEN - bytes_written;
pp->sendthis = strdup(eob);
pp->sendsize = len;
pp->sendleft = len - bytes_written;
}
else
/* Successfully sent so adjust the response timeout relative to now */
@@ -1444,7 +1542,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
*dophase_done = FALSE; /* not done yet */
/* Start the first command in the DO phase */
result = smtp_mail(conn);
result = smtp_perform_mail(conn);
if(result)
return result;
@@ -1488,25 +1586,6 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
return result;
}
/***********************************************************************
*
* smtp_quit()
*
* Performs the quit action prior to sclose() being called.
*/
static CURLcode smtp_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
/* Send the QUIT command */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
if(!result)
state(conn, SMTP_QUIT);
return result;
}
/***********************************************************************
*
* smtp_disconnect()
@@ -1526,7 +1605,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn,
/* The SMTP session may or may not have been allocated/setup at this
point! */
if(!dead_connection && smtpc->pp.conn)
if(!smtp_quit(conn))
if(!smtp_perform_quit(conn))
(void)smtp_block_statemach(conn); /* ignore errors on QUIT */
/* Disconnect from the server */
@@ -1640,18 +1719,90 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
return CURLE_OK;
}
/***********************************************************************
*
* smtp_parse_url_options()
*
* Parse the URL login options.
*/
static CURLcode smtp_parse_url_options(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *options = conn->options;
const char *ptr = options;
if(options) {
const char *key = ptr;
while(*ptr && *ptr != '=')
ptr++;
if(strnequal(key, "AUTH", 4)) {
const char *value = ptr + 1;
if(strequal(value, "*"))
smtpc->prefmech = SASL_AUTH_ANY;
else if(strequal(value, "LOGIN"))
smtpc->prefmech = SASL_MECH_LOGIN;
else if(strequal(value, "PLAIN"))
smtpc->prefmech = SASL_MECH_PLAIN;
else if(strequal(value, "CRAM-MD5"))
smtpc->prefmech = SASL_MECH_CRAM_MD5;
else if(strequal(value, "DIGEST-MD5"))
smtpc->prefmech = SASL_MECH_DIGEST_MD5;
else if(strequal(value, "GSSAPI"))
smtpc->prefmech = SASL_MECH_GSSAPI;
else if(strequal(value, "NTLM"))
smtpc->prefmech = SASL_MECH_NTLM;
else
smtpc->prefmech = SASL_AUTH_NONE;
}
else
result = CURLE_URL_MALFORMAT;
}
return result;
}
/***********************************************************************
*
* smtp_parse_url_path()
*
* Parse the URL path into separate path components.
*/
static CURLcode smtp_parse_url_path(struct connectdata *conn)
{
/* The SMTP struct is already initialised in smtp_connect() */
struct SessionHandle *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *path = data->state.path;
char localhost[HOSTNAME_MAX + 1];
/* Calculate the path if necessary */
if(!*path) {
if(!Curl_gethostname(localhost, sizeof(localhost)))
path = localhost;
else
path = "localhost";
}
/* URL decode the path and use it as the domain in our EHLO */
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
}
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
{
/* When sending a SMTP payload we must detect CRLF. sequences making sure
they are sent as CRLF.. instead, as a . on the beginning of a line will
be deleted by the server when not part of an EOB terminator and a
genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of
data by the server.
data by the server
*/
ssize_t i;
ssize_t si;
struct smtp_conn *smtpc = &conn->proto.smtpc;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->state.proto.smtp;
/* Do we need to allocate the scatch buffer? */
if(!data->state.scratch) {
@@ -1666,36 +1817,46 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
/* This loop can be improved by some kind of Boyer-Moore style of
approach but that is saved for later... */
for(i = 0, si = 0; i < nread; i++) {
if(SMTP_EOB[smtpc->eob] == data->req.upload_fromhere[i])
smtpc->eob++;
else if(smtpc->eob) {
if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
smtp->eob++;
/* Is the EOB potentially the terminating CRLF? */
if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob)
smtp->trailing_crlf = TRUE;
else
smtp->trailing_crlf = FALSE;
}
else if(smtp->eob) {
/* A previous substring matched so output that first */
memcpy(&data->state.scratch[si], SMTP_EOB, smtpc->eob);
si += smtpc->eob;
memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
si += smtp->eob;
/* Then compare the first byte */
if(SMTP_EOB[0] == data->req.upload_fromhere[i])
smtpc->eob = 1;
smtp->eob = 1;
else
smtpc->eob = 0;
smtp->eob = 0;
/* Reset the trailing CRLF flag as there was more data */
smtp->trailing_crlf = FALSE;
}
/* Do we have a match for CRLF. as per RFC-2821, sect. 4.5.2 */
if(SMTP_EOB_FIND_LEN == smtpc->eob) {
/* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */
if(SMTP_EOB_FIND_LEN == smtp->eob) {
/* Copy the replacement data to the target buffer */
memcpy(&data->state.scratch[si], SMTP_EOB_REPL, SMTP_EOB_REPL_LEN);
si += SMTP_EOB_REPL_LEN;
smtpc->eob = 0;
smtp->eob = 0;
}
else if(!smtpc->eob)
else if(!smtp->eob)
data->state.scratch[si++] = data->req.upload_fromhere[i];
}
if(smtpc->eob) {
if(smtp->eob) {
/* A substring matched before processing ended so output that now */
memcpy(&data->state.scratch[si], SMTP_EOB, smtpc->eob);
si += smtpc->eob;
smtpc->eob = 0;
memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
si += smtp->eob;
smtp->eob = 0;
}
if(si != nread) {

View File

@@ -60,6 +60,9 @@ typedef enum {
struct SMTP {
curl_pp_transfer transfer;
struct curl_slist *rcpt; /* Recipient list */
size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */
bool trailing_crlf; /* Specifies if the tailing CRLF is present */
};
/* smtp_conn is used for struct connection-oriented data in the connectdata
@@ -69,9 +72,8 @@ struct smtp_conn {
smtpstate state; /* Always use smtp.c:state() to change state! */
bool ssldone; /* Is connect() over SSL done? */
char *domain; /* Client address/name to send in the EHLO */
size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */
unsigned int authmechs; /* Accepted authentication mechanisms */
unsigned int prefmech; /* Preferred authentication mechanism */
unsigned int authused; /* Auth mechanism used for the connection */
bool tls_supported; /* StartTLS capability supported by server */
bool size_supported; /* If server supports SIZE extension according to

View File

@@ -435,7 +435,7 @@ int cert_stuff(struct connectdata *conn,
PKCS12_PBE_add();
if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
&ca)) {
&ca)) {
failf(data,
"could not parse PKCS12 file, check password, OpenSSL error %s",
ERR_error_string(ERR_get_error(), NULL) );
@@ -447,54 +447,53 @@ int cert_stuff(struct connectdata *conn,
if(SSL_CTX_use_certificate(ctx, x509) != 1) {
failf(data, SSL_CLIENT_CERT_ERR);
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
return 0;
goto fail;
}
if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
failf(data, "unable to use private key from PKCS12 file '%s'",
cert_file);
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
return 0;
goto fail;
}
if(!SSL_CTX_check_private_key (ctx)) {
failf(data, "private key from PKCS12 file '%s' "
"does not match certificate in same file", cert_file);
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
return 0;
goto fail;
}
/* Set Certificate Verification chain */
if(ca && sk_X509_num(ca)) {
for(i = 0; i < sk_X509_num(ca); i++) {
if(!SSL_CTX_add_extra_chain_cert(ctx,sk_X509_value(ca, i))) {
/*
* Note that sk_X509_pop() is used below to make sure the cert is
* removed from the stack properly before getting passed to
* SSL_CTX_add_extra_chain_cert(). Previously we used
* sk_X509_value() instead, but then we'd clean it in the subsequent
* sk_X509_pop_free() call.
*/
X509 *x = sk_X509_pop(ca);
if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
failf(data, "cannot add certificate to certificate chain");
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
return 0;
goto fail;
}
if(!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) {
/* SSL_CTX_add_client_CA() seems to work with either sk_* function,
* presumably because it duplicates what we pass to it.
*/
if(!SSL_CTX_add_client_CA(ctx, x)) {
failf(data, "cannot add certificate to client CA list");
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
return 0;
goto fail;
}
}
}
cert_done = 1;
fail:
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
cert_done = 1;
break;
if(!cert_done)
return 0; /* failure! */
#else
failf(data, "file type P12 for certificate not supported");
return 0;
@@ -2205,14 +2204,7 @@ static CURLcode servercert(struct connectdata *conn,
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
buffer, BUFSIZE);
if(rc) {
if(strict)
failf(data, "SSL: couldn't get X509-subject!");
X509_free(connssl->server_cert);
connssl->server_cert = NULL;
return CURLE_SSL_CONNECT_ERROR;
}
infof(data, "\t subject: %s\n", buffer);
infof(data, "\t subject: %s\n", rc?"[NONE]":buffer);
certdate = X509_get_notBefore(connssl->server_cert);
asn1_output(certdate, buffer, BUFSIZE);
@@ -2553,7 +2545,7 @@ static ssize_t ossl_send(struct connectdata *conn,
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
if(rc < 0) {
if(rc <= 0) {
err = SSL_get_error(conn->ssl[sockindex].handle, rc);
switch(err) {
@@ -2602,7 +2594,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
if(nread < 0) {
if(nread <= 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);

499
lib/url.c
View File

@@ -141,9 +141,12 @@ find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
static void conn_free(struct connectdata *conn);
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
static CURLcode do_init(struct connectdata *conn);
static CURLcode parse_url_userpass(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd);
static CURLcode parse_url_login(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd, char *options);
static CURLcode parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
/*
* Protocol table.
*/
@@ -261,7 +264,7 @@ static const struct Curl_handler Curl_handler_dummy = {
PROTOPT_NONE /* flags */
};
void Curl_freeset(struct SessionHandle * data)
void Curl_freeset(struct SessionHandle *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
@@ -275,7 +278,7 @@ void Curl_freeset(struct SessionHandle * data)
data->change.referer = NULL;
}
static CURLcode setstropt(char **charp, char * s)
static CURLcode setstropt(char **charp, char *s)
{
/* Release the previous storage at `charp' and replace by a dynamic storage
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
@@ -294,48 +297,47 @@ static CURLcode setstropt(char **charp, char * s)
return CURLE_OK;
}
static CURLcode setstropt_userpwd(char *option, char **user_storage,
char **pwd_storage)
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
char **optionsp)
{
char* separator;
CURLcode result = CURLE_OK;
char *user = NULL;
char *passwd = NULL;
char *options = NULL;
if(!option) {
/* we treat a NULL passed in as a hint to clear existing info */
Curl_safefree(*user_storage);
*user_storage = (char *) NULL;
Curl_safefree(*pwd_storage);
*pwd_storage = (char *) NULL;
return CURLE_OK;
/* Parse the login details if specified. It not then we treat NULL as a hint
to clear the existing data */
if(option) {
result = parse_login_details(option, strlen(option),
(userp ? &user : NULL),
(passwdp ? &passwd : NULL),
(optionsp ? &options : NULL));
}
separator = strchr(option, ':');
if(separator != NULL) {
/* store username part of option */
char * p;
size_t username_len = (size_t)(separator-option);
p = malloc(username_len+1);
if(!p)
result = CURLE_OUT_OF_MEMORY;
else {
memcpy(p, option, username_len);
p[username_len] = '\0';
Curl_safefree(*user_storage);
*user_storage = p;
if(!result) {
/* Store the username part of option if required */
if(userp) {
Curl_safefree(*userp);
*userp = user;
}
/* store password part of option */
if(result == CURLE_OK)
result = setstropt(pwd_storage, separator+1);
}
else {
result = setstropt(user_storage, option);
/* Store the password part of option if required */
if(passwdp) {
Curl_safefree(*passwdp);
*passwdp = passwd;
}
/* Store the options part of option if required */
if(optionsp) {
Curl_safefree(*optionsp);
*optionsp = options;
}
}
return result;
}
CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src)
CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
{
CURLcode r = CURLE_OK;
enum dupstring i;
@@ -1135,41 +1137,44 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
if(argptr == NULL)
break;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
if(Curl_raw_equal(argptr, "ALL")) {
/* clear all cookies */
Curl_cookie_clearall(data->cookies);
break;
}
else if(Curl_raw_equal(argptr, "SESS")) {
/* clear session cookies */
Curl_cookie_clearsess(data->cookies);
break;
}
else if(Curl_raw_equal(argptr, "FLUSH")) {
/* flush cookies to file */
Curl_flush_cookies(data, 0);
break;
}
else {
if(!data->cookies)
/* if cookie engine was not running, activate it */
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
if(!data->cookies)
/* if cookie engine was not running, activate it */
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
argptr = strdup(argptr);
if(!argptr) {
result = CURLE_OUT_OF_MEMORY;
}
else {
argptr = strdup(argptr);
if(!argptr) {
result = CURLE_OUT_OF_MEMORY;
break;
if(checkprefix("Set-Cookie:", argptr))
/* HTTP Header format line */
Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
else
/* Netscape format line */
Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
free(argptr);
}
}
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
if(checkprefix("Set-Cookie:", argptr))
/* HTTP Header format line */
Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
else
/* Netscape format line */
Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
free(argptr);
break;
#endif /* CURL_DISABLE_COOKIES */
@@ -1534,11 +1539,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
case CURLOPT_USERPWD:
/*
* user:password to use in the operation
* user:password;options to use in the operation
*/
result = setstropt_userpwd(va_arg(param, char *),
&data->set.str[STRING_USERNAME],
&data->set.str[STRING_PASSWORD]);
&data->set.str[STRING_PASSWORD],
&data->set.str[STRING_OPTIONS]);
break;
case CURLOPT_USERNAME:
/*
@@ -1611,7 +1617,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*/
result = setstropt_userpwd(va_arg(param, char *),
&data->set.str[STRING_PROXYUSERNAME],
&data->set.str[STRING_PROXYPASSWORD]);
&data->set.str[STRING_PROXYPASSWORD], NULL);
break;
case CURLOPT_PROXYUSERNAME:
/*
@@ -2243,20 +2249,27 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_MAIL_FROM:
/* Set the SMTP mail originator */
result = setstropt(&data->set.str[STRING_MAIL_FROM],
va_arg(param, char *));
break;
case CURLOPT_MAIL_AUTH:
/* Set the SMTP auth originator */
result = setstropt(&data->set.str[STRING_MAIL_AUTH],
va_arg(param, char *));
break;
case CURLOPT_MAIL_RCPT:
/* get a list of mail recipients */
/* Set the list of mail recipients */
data->set.mail_rcpt = va_arg(param, struct curl_slist *);
break;
case CURLOPT_SASL_IR:
/* Enable/disable SASL initial response */
data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_RTSP_REQUEST:
{
/*
@@ -2452,6 +2465,7 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->options);
Curl_safefree(conn->proxyuser);
Curl_safefree(conn->proxypasswd);
Curl_safefree(conn->allocptr.proxyuserpwd);
@@ -3650,8 +3664,7 @@ static CURLcode findprotocol(struct SessionHandle *data,
static CURLcode parseurlandfillconn(struct SessionHandle *data,
struct connectdata *conn,
bool *prot_missing,
char *user,
char *passwd)
char *user, char *passwd, char *options)
{
char *at;
char *fragment;
@@ -3768,6 +3781,10 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
protop = "LDAP";
else if(checkprefix("IMAP.", conn->host.name))
protop = "IMAP";
else if(checkprefix("SMTP.", conn->host.name))
protop = "smtp";
else if(checkprefix("POP3.", conn->host.name))
protop = "pop3";
else {
protop = "http";
}
@@ -3865,11 +3882,11 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
data->change.url_alloc = TRUE; /* free this later */
}
/*************************************************************
* Parse a user name and password in the URL and strip it out
* of the host name
*************************************************************/
result = parse_url_userpass(data, conn, user, passwd);
/*
* Parse the login details from the URL and strip them out of
* the host name
*/
result = parse_url_login(data, conn, user, passwd, options);
if(result != CURLE_OK)
return result;
@@ -4193,34 +4210,37 @@ static CURLcode parse_proxy(struct SessionHandle *data,
/* Is there a username and password given in this proxy url? */
atsign = strchr(proxyptr, '@');
if(atsign) {
char proxyuser[MAX_CURL_USER_LENGTH];
char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
proxypasswd[0] = 0;
if(1 <= sscanf(proxyptr,
"%" MAX_CURL_USER_LENGTH_TXT"[^:@]:"
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
proxyuser, proxypasswd)) {
CURLcode res = CURLE_OK;
CURLcode res = CURLE_OK;
char *proxyuser = NULL;
char *proxypasswd = NULL;
res = parse_login_details(proxyptr, atsign - proxyptr,
&proxyuser, &proxypasswd, NULL);
if(!res) {
/* found user and password, rip them out. note that we are
unescaping them, as there is otherwise no way to have a
username or password with reserved characters like ':' in
them. */
Curl_safefree(conn->proxyuser);
conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
else
conn->proxyuser = strdup("");
if(!conn->proxyuser)
res = CURLE_OUT_OF_MEMORY;
else {
Curl_safefree(conn->proxypasswd);
conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
else
conn->proxypasswd = strdup("");
if(!conn->proxypasswd)
res = CURLE_OUT_OF_MEMORY;
}
if(CURLE_OK == res) {
if(!res) {
conn->bits.proxy_user_passwd = TRUE; /* enable it */
atsign++; /* the right side of the @-letter */
@@ -4229,10 +4249,13 @@ static CURLcode parse_proxy(struct SessionHandle *data,
else
res = CURLE_OUT_OF_MEMORY;
}
if(res)
return res;
}
Curl_safefree(proxyuser);
Curl_safefree(proxypasswd);
if(res)
return res;
}
/* start scanning for port number at this point */
@@ -4326,8 +4349,10 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
#endif /* CURL_DISABLE_PROXY */
/*
* parse_url_login()
*
* Parse a user name and password in the URL and strip it out of the host name
* Parse the login details (user name, password and options) from the URL and
* strip them out of the host name
*
* Inputs: data->set.use_netrc (CURLOPT_NETRC)
* conn->host.name
@@ -4335,31 +4360,38 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
* Outputs: (almost :- all currently undefined)
* conn->bits.user_passwd - non-zero if non-default passwords exist
* user - non-zero length if defined
* passwd - ditto
* passwd - non-zero length if defined
* options - non-zero length if defined
* conn->host.name - remove user name and password
*/
static CURLcode parse_url_userpass(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd)
static CURLcode parse_url_login(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd, char *options)
{
CURLcode result = CURLE_OK;
char *userp = NULL;
char *passwdp = NULL;
char *optionsp = NULL;
/* At this point, we're hoping all the other special cases have
* been taken care of, so conn->host.name is at most
* [user[:password]]@]hostname
* [user[:password][;options]]@]hostname
*
* We need somewhere to put the embedded details, so do that first.
*/
char *ptr=strchr(conn->host.name, '@');
char *userpass = conn->host.name;
char *ptr = strchr(conn->host.name, '@');
char *login = conn->host.name;
user[0] =0; /* to make everything well-defined */
passwd[0]=0;
user[0] = 0; /* to make everything well-defined */
passwd[0] = 0;
options[0] = 0;
/* We will now try to extract the
* possible user+password pair in a string like:
* possible login information in a string like:
* ftp://user:password@ftp.my.site:8021/README */
if(ptr != NULL) {
/* there's a user+password given here, to the left of the @ */
if(ptr) {
/* There's login information to the left of the @ */
conn->host.name = ++ptr;
@@ -4369,46 +4401,183 @@ static CURLcode parse_url_userpass(struct SessionHandle *data,
* set user/passwd, but doing that first adds more cases here :-(
*/
conn->bits.userpwd_in_url = TRUE;
if(data->set.use_netrc != CURL_NETRC_REQUIRED) {
/* We could use the one in the URL */
/* 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(userp) {
char *newname;
conn->bits.user_passwd = TRUE; /* enable user+password */
/* We have a user in the URL */
conn->bits.userpwd_in_url = TRUE;
conn->bits.user_passwd = TRUE; /* enable user+password */
if(*userpass != ':') {
/* the name is given, get user+password */
sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:@]:"
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
user, passwd);
/* Decode the user */
newname = curl_easy_unescape(data, userp, 0, NULL);
if(!newname)
return CURLE_OUT_OF_MEMORY;
if(strlen(newname) < MAX_CURL_USER_LENGTH)
strcpy(user, newname);
free(newname);
}
if(passwdp) {
/* We have a password in the URL so decode it */
char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
if(!newpasswd)
return CURLE_OUT_OF_MEMORY;
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
strcpy(passwd, newpasswd);
free(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)
return CURLE_OUT_OF_MEMORY;
if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
strcpy(options, newoptions);
free(newoptions);
}
}
else
/* no name given, get the password only */
sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", passwd);
if(user[0]) {
char *newname=curl_easy_unescape(data, user, 0, NULL);
if(!newname)
return CURLE_OUT_OF_MEMORY;
if(strlen(newname) < MAX_CURL_USER_LENGTH)
strcpy(user, newname);
/* if the new name is longer than accepted, then just use
the unconverted name, it'll be wrong but what the heck */
free(newname);
}
if(passwd[0]) {
/* we have a password found in the URL, decode it! */
char *newpasswd=curl_easy_unescape(data, passwd, 0, NULL);
if(!newpasswd)
return CURLE_OUT_OF_MEMORY;
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
strcpy(passwd, newpasswd);
free(newpasswd);
}
Curl_safefree(userp);
Curl_safefree(passwdp);
Curl_safefree(optionsp);
}
}
return CURLE_OK;
return result;
}
/*
* parse_login_details()
*
* This is used to parse a login string for user name, password and options in
* the following formats:
*
* user
* user:password
* user:password;options
* user;options
* user;options:password
* :password
* :password;options
* ;options
* ;options:password
*
* Parameters:
*
* login [in] - The login string.
* len [in] - The length of the login string.
* userp [in/out] - The address where a pointer to newly allocated memory
* holding the user will be stored upon completion.
* passdwp [in/out] - The address where a pointer to newly allocated memory
* holding the password will be stored upon completion.
* optionsp [in/out] - The address where a pointer to newly allocated memory
* holding the options will be stored upon completion.
*
* Returns CURLE_OK on success.
*/
static CURLcode parse_login_details(const char *login, const size_t len,
char **userp, char **passwdp,
char **optionsp)
{
CURLcode result = CURLE_OK;
char *ubuf = NULL;
char *pbuf = NULL;
char *obuf = NULL;
const char *psep = NULL;
const char *osep = NULL;
size_t ulen;
size_t plen;
size_t olen;
/* Attempt to find the password separator */
if(passwdp) {
psep = strchr(login, ':');
/* Within the constraint of the login string */
if(psep >= login + len)
psep = NULL;
}
/* Attempt to find the options separator */
if(optionsp) {
osep = strchr(login, ';');
/* Within the constraint of the login string */
if(osep >= login + len)
osep = NULL;
}
/* Calculate the portion lengths */
ulen = (psep ?
(size_t)(osep && psep > osep ? osep - login : psep - login) :
(osep ? (size_t)(osep - login) : len));
plen = (psep ?
(osep && osep > psep ? (size_t)(osep - psep) :
(size_t)(login + len - psep)) - 1 : 0);
olen = (osep ?
(psep && psep > osep ? (size_t)(psep - osep) :
(size_t)(login + len - osep)) - 1 : 0);
/* Allocate the user portion buffer */
if(userp && ulen) {
ubuf = malloc(ulen + 1);
if(!ubuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Allocate the password portion buffer */
if(!result && passwdp && plen) {
pbuf = malloc(plen + 1);
if(!pbuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Allocate the options portion buffer */
if(!result && optionsp && olen) {
obuf = malloc(olen + 1);
if(!obuf)
result = CURLE_OUT_OF_MEMORY;
}
if(!result) {
/* Store the user portion if necessary */
if(ubuf) {
memcpy(ubuf, login, ulen);
ubuf[ulen] = '\0';
Curl_safefree(*userp);
*userp = ubuf;
}
/* Store the password portion if necessary */
if(pbuf) {
memcpy(pbuf, psep + 1, plen);
pbuf[plen] = '\0';
Curl_safefree(*passwdp);
*passwdp = pbuf;
}
/* Store the options portion if necessary */
if(obuf) {
memcpy(obuf, osep + 1, olen);
obuf[olen] = '\0';
Curl_safefree(*optionsp);
*optionsp = obuf;
}
}
return result;
}
/*************************************************************
@@ -4531,20 +4700,26 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
}
/*
* Override a user name and password from the URL with that in the
* CURLOPT_USERPWD option or a .netrc file, if applicable.
* Override the login details from the URL with that in the CURLOPT_USERPWD
* option or a .netrc file, if applicable.
*/
static void override_userpass(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd)
static void override_login(struct SessionHandle *data,
struct connectdata *conn,
char *user, char *passwd, char *options)
{
if(data->set.str[STRING_USERNAME] != NULL) {
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*/
user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */
}
if(data->set.str[STRING_PASSWORD] != NULL) {
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*/
passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */
}
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 */
}
conn->bits.netrc = FALSE;
@@ -4570,32 +4745,48 @@ static void override_userpass(struct SessionHandle *data,
/*
* Set password so it's available in the connection.
*/
static CURLcode set_userpass(struct connectdata *conn,
const char *user, const char *passwd)
static CURLcode set_login(struct connectdata *conn,
const char *user, const char *passwd,
const char *options)
{
/* If our protocol needs a password and we have none, use the defaults */
if((conn->handler->flags & PROTOPT_NEEDSPWD) &&
!conn->bits.user_passwd) {
CURLcode result = CURLE_OK;
/* If our protocol needs a password and we have none, use the defaults */
if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
/* Store the default user */
conn->user = strdup(CURL_DEFAULT_USER);
/* Store the default password */
if(conn->user)
conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
else
conn->passwd = NULL;
/* This is the default password, so DON'T set conn->bits.user_passwd */
}
else {
/* store user + password, zero-length if not set */
/* Store the user, zero-length if not set */
conn->user = strdup(user);
/* Store the password (only if user is present), zero-length if not set */
if(conn->user)
conn->passwd = strdup(passwd);
else
conn->passwd = NULL;
}
if(!conn->user || !conn->passwd)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
if(!conn->user || !conn->passwd)
result = CURLE_OUT_OF_MEMORY;
/* Store the options, null if not set */
if(!result && options[0]) {
conn->options = strdup(options);
if(!conn->options)
result = CURLE_OUT_OF_MEMORY;
}
return result;
}
/*************************************************************
@@ -4761,12 +4952,13 @@ static CURLcode create_conn(struct SessionHandle *data,
struct connectdata **in_connect,
bool *async)
{
CURLcode result=CURLE_OK;
CURLcode result = CURLE_OK;
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];
bool reuse;
char *proxy = NULL;
bool prot_missing = FALSE;
@@ -4835,7 +5027,8 @@ static CURLcode create_conn(struct SessionHandle *data,
conn->host.name = conn->host.rawalloc;
conn->host.name[0] = 0;
result = parseurlandfillconn(data, conn, &prot_missing, user, passwd);
result = parseurlandfillconn(data, conn, &prot_missing, user, passwd,
options);
if(result != CURLE_OK)
return result;
@@ -5010,6 +5203,9 @@ static CURLcode create_conn(struct SessionHandle *data,
-1, NULL); /* no upload */
}
/* since we skip do_init() */
Curl_speedinit(data);
return result;
}
#endif
@@ -5028,12 +5224,9 @@ static CURLcode create_conn(struct SessionHandle *data,
if(result != CURLE_OK)
return result;
/*************************************************************
* Check for an overridden user name and password, then set it
* for use
*************************************************************/
override_userpass(data, conn, user, passwd);
result = set_userpass(conn, user, passwd);
/* 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;

View File

@@ -243,6 +243,7 @@ struct curl_schannel_cred {
CredHandle cred_handle;
TimeStamp time_stamp;
int refcount;
bool cached;
};
struct curl_schannel_ctxt {
@@ -324,6 +325,7 @@ struct ssl_connect_data {
#ifdef USE_AXTLS
SSL_CTX* ssl_ctx;
SSL* ssl;
ssl_connect_state connecting_state;
#endif /* USE_AXTLS */
#ifdef USE_SCHANNEL
struct curl_schannel_cred *cred;
@@ -859,6 +861,7 @@ struct connectdata {
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
char *proxyuser; /* proxy user name string, allocated */
char *proxypasswd; /* proxy password string, allocated */
@@ -1136,8 +1139,7 @@ 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_USER_LENGTH_TXT "255"
#define MAX_CURL_PASSWORD_LENGTH_TXT "255"
#define MAX_CURL_OPTIONS_LENGTH 256
struct auth {
unsigned long want; /* Bitmask set to the authentication methods wanted by
@@ -1352,6 +1354,7 @@ enum dupstring {
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
STRING_USERNAME, /* <username>, if used */
STRING_PASSWORD, /* <password>, if used */
STRING_OPTIONS, /* <options>, if used */
STRING_PROXYUSERNAME, /* Proxy <username>, if used */
STRING_PROXYPASSWORD, /* Proxy <password>, if used */
STRING_NOPROXY, /* List of hosts which should not use the proxy, if
@@ -1562,6 +1565,7 @@ struct UserDefined {
long socks5_gssapi_nec; /* flag to support nec socks5 server */
#endif
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
bool sasl_ir; /* Enable/disable SASL initial response */
/* Common RTSP header options */
Curl_RtspReq rtspreq; /* RTSP request type */
long rtspversion; /* like httpversion, for RTSP */

View File

@@ -9,7 +9,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
@@ -142,7 +142,7 @@ make -s dist VERSION=$version
bzip2="curl-$version.tar.bz2"
echo "Generating $bzip2"
gzip -dc $targz | bzip2 --best - > $bzip2
gzip -dc $targz | bzip2 --best > $bzip2
############################################################################
#

View File

@@ -72,7 +72,7 @@ CFLAGS += -d_WIN32_WINNT=0x0501 -dENABLE_IPV6
!ifdef %zlib_root
ZLIB_ROOT = $(%zlib_root)
!else
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.7
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.8
!endif
!ifdef %libssh2_root

View File

@@ -66,6 +66,15 @@ curl_LDFLAGS = @LIBMETALINK_LDFLAGS@
curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMETALINK_CPPFLAGS)
curl_DEPENDENCIES = $(top_builddir)/lib/libcurl.la
# if unit tests are enabled, build a static library to link them with
if BUILD_UNITTESTS
noinst_LTLIBRARIES = libcurltool.la
libcurltool_la_CPPFLAGS = $(LIBMETALINK_CPPFLAGS) $(AM_CPPFLAGS)
libcurltool_la_CFLAGS = -DUNITTESTS
libcurltool_la_LDFLAGS = -static $(LINKFLAGS)
libcurltool_la_SOURCES = $(curl_SOURCES)
endif
BUILT_SOURCES = tool_hugehelp.c
CLEANFILES = tool_hugehelp.c
# Use the C locale to ensure that only ASCII characters appear in the

View File

@@ -22,7 +22,7 @@ BCCDIR = $(MAKEDIR)\..
# Edit the path below to point to the base of your Zlib sources.
!ifndef ZLIB_PATH
ZLIB_PATH = ..\..\zlib-1.2.7
ZLIB_PATH = ..\..\zlib-1.2.8
!endif
# Edit the path below to point to the base of your OpenSSL package.

View File

@@ -7,14 +7,14 @@
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-spi-winidn
##
## Hint: you can also set environment vars to control the build, f.e.:
## set ZLIB_PATH=c:/zlib-1.2.7
## set ZLIB_PATH=c:/zlib-1.2.8
## set ZLIB=1
#
###########################################################################
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.7
ZLIB_PATH = ../../zlib-1.2.8
endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH

View File

@@ -14,7 +14,7 @@ endif
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.7
ZLIB_PATH = ../../zlib-1.2.8
endif
# Edit the path below to point to the base of your OpenSSL package.

View File

@@ -60,7 +60,7 @@ OPENSSL_PATH = ../../openssl-0.9.8y
!ENDIF
!IFNDEF ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.7
ZLIB_PATH = ../../zlib-1.2.8
!ENDIF
!IFNDEF MACHINE

View File

@@ -80,6 +80,7 @@ struct Configurable {
char *mail_from;
struct curl_slist *mail_rcpt;
char *mail_auth;
bool sasl_ir; /* Enable/disable SASL initial response */
bool proxytunnel;
bool ftp_append; /* APPE on ftp */
bool mute; /* don't show messages, --silent given */

View File

@@ -173,6 +173,7 @@ static const struct LongShort aliases[]= {
{"$H", "mail-auth", TRUE},
{"$I", "post303", FALSE},
{"$J", "metalink", FALSE},
{"$K", "sasl-ir", FALSE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
{"2", "sslv2", FALSE},
@@ -285,6 +286,105 @@ static const struct feat feats[] = {
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
};
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
* We allow ':' and '\' to be escaped by '\' so that we can use certificate
* nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
* for details. */
#ifndef UNITTESTS
static
#endif
void parse_cert_parameter(const char *cert_parameter,
char **certname,
char **passphrase)
{
size_t param_length = strlen(cert_parameter);
size_t span;
const char *param_place = NULL;
char *certname_place = NULL;
*certname = NULL;
*passphrase = NULL;
/* most trivial assumption: cert_parameter is empty */
if(param_length == 0)
return;
/* next less trivial: cert_parameter contains no colon nor backslash; this
* means no passphrase was given and no characters escaped */
if(!strpbrk(cert_parameter, ":\\")) {
*certname = strdup(cert_parameter);
return;
}
/* deal with escaped chars; find unescaped colon if it exists */
certname_place = malloc(param_length + 1);
if(!certname_place)
return;
*certname = certname_place;
param_place = cert_parameter;
while(*param_place) {
span = strcspn(param_place, ":\\");
strncpy(certname_place, param_place, span);
param_place += span;
certname_place += span;
/* we just ate all the non-special chars. now we're on either a special
* char or the end of the string. */
switch(*param_place) {
case '\0':
break;
case '\\':
param_place++;
switch(*param_place) {
case '\0':
*certname_place++ = '\\';
break;
case '\\':
*certname_place++ = '\\';
param_place++;
break;
case ':':
*certname_place++ = ':';
param_place++;
break;
default:
*certname_place++ = '\\';
*certname_place++ = *param_place;
param_place++;
break;
}
break;
case ':':
/* Since we live in a world of weirdness and confusion, the win32
dudes can use : when using drive letters and thus c:\file:password
needs to work. In order not to break compatibility, we still use : as
separator, but we try to detect when it is used for a file name! On
windows. */
#ifdef WIN32
if(param_place &&
(param_place == &cert_parameter[1]) &&
(cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
(ISALPHA(cert_parameter[0])) ) {
/* colon in the second column, followed by a backslash, and the
first character is an alphabetic letter:
this is a drive letter colon */
*certname_place++ = ':';
param_place++;
break;
}
#endif
/* escaped colons and Windows drive letter colons were handled
* above; if we're still here, this is a separating colon */
param_place++;
if(strlen(param_place) > 0) {
*passphrase = strdup(param_place);
}
goto done;
}
}
done:
*certname_place = '\0';
}
ParameterError getparameter(char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
bool *usedarg, /* set to TRUE if the arg
@@ -858,6 +958,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
#endif
break;
}
case 'K': /* --sasl-ir */
config->sasl_ir = TRUE;
break;
}
break;
case '#': /* --progress-bar */
@@ -1203,30 +1306,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break;
default: /* certificate file */
{
char *ptr = strchr(nextarg, ':');
/* Since we live in a world of weirdness and confusion, the win32
dudes can use : when using drive letters and thus
c:\file:password needs to work. In order not to break
compatibility, we still use : as separator, but we try to detect
when it is used for a file name! On windows. */
#ifdef WIN32
if(ptr &&
(ptr == &nextarg[1]) &&
(nextarg[2] == '\\' || nextarg[2] == '/') &&
(ISALPHA(nextarg[0])) )
/* colon in the second column, followed by a backslash, and the
first character is an alphabetic letter:
this is a drive letter colon */
ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
#endif
if(ptr) {
/* we have a password too */
*ptr = '\0';
ptr++;
GetStr(&config->key_passwd, ptr);
char *certname, *passphrase;
parse_cert_parameter(nextarg, &certname, &passphrase);
Curl_safefree(config->cert);
config->cert = certname;
if(passphrase) {
Curl_safefree(config->key_passwd);
config->key_passwd = passphrase;
}
GetStr(&config->cert, nextarg);
cleanarg(nextarg);
}
}

View File

@@ -45,5 +45,11 @@ ParameterError getparameter(char *flag,
bool *usedarg,
struct Configurable *config);
#ifdef UNITTESTS
void parse_cert_parameter(const char *cert_parameter,
char **certname,
char **passphrase);
#endif
#endif /* HEADER_CURL_TOOL_GETPARAM_H */

View File

@@ -173,6 +173,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"
" -S, --show-error "
"Show error. With -s, make curl show errors when they occur",
" -s, --silent Silent mode. Don't output anything",

View File

@@ -55,6 +55,9 @@
int vms_show = 0;
#endif
/* if we build a static library for unit tests, there is no main() function */
#ifndef UNITTESTS
/*
* Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
* open before starting to run. Otherwise, the first three network
@@ -118,3 +121,4 @@ int main(int argc, char *argv[])
#endif
}
#endif /* ndef UNITTESTS */

View File

@@ -1320,6 +1320,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
/* new in 7.31.0 */
if(config->sasl_ir)
my_setopt(curl, CURLOPT_SASL_IR, (long)TRUE);
/* initialize retry vars for loop below */
retry_sleep_default = (config->retry_delay) ?
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */

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
@@ -322,13 +322,19 @@ ParameterError str2offset(curl_off_t *val, const char *str)
ParameterError checkpasswd(const char *kind, /* for what purpose */
char **userpwd) /* pointer to allocated string */
{
char *ptr;
char *psep;
char *osep;
if(!*userpwd)
return PARAM_OK;
ptr = strchr(*userpwd, ':');
if(!ptr) {
/* Attempt to find the password separator */
psep = strchr(*userpwd, ':');
/* Attempt to find the options separator */
osep = strchr(*userpwd, ';');
if(!psep && **userpwd != ';') {
/* no password present, prompt for one */
char passwd[256] = "";
char prompt[256];
@@ -336,6 +342,9 @@ ParameterError checkpasswd(const char *kind, /* for what purpose */
size_t userlen = strlen(*userpwd);
char *passptr;
if(osep)
*osep = '\0';
/* build a nice-looking prompt */
curlx_msnprintf(prompt, sizeof(prompt),
"Enter %s password for user '%s':",
@@ -345,6 +354,9 @@ ParameterError checkpasswd(const char *kind, /* for what purpose */
getpass_r(prompt, passwd, sizeof(passwd));
passwdlen = strlen(passwd);
if(osep)
*osep = ';';
/* extend the allocated memory area to fit the password too */
passptr = realloc(*userpwd,
passwdlen + 1 + /* an extra for the colon */

View File

@@ -107,6 +107,8 @@ For FTP/SMTP/POP/IMAP, these are supported:
REPLY [command] [return value] [response string]
- Changes how the server responds to the [command]. [response string] is
evaluated as a perl string, so it can contain embedded \r\n, for example.
There's a special [command] named "welcome" (without quotes) which is the
string sent immediately on connect as a welcome.
COUNT [command] [num]
- Do the REPLY change for [command] only [num] times and then go back to the
built-in approach
@@ -255,7 +257,9 @@ data that is defined within the <reply><data></data></reply> section.
If there's no test number found above, the HTTP test server will use the
number following the last dot in the given hostname (made so that a CONNECT
can still pass on test number) so that "foo.bar.123" gets treated as test case
123.
123. Alternatively, if an ipv6-address is provided to CONNECT, the last
hexadecimal group in the address will be used as the test numer! For example
the address "[1234::ff]" would be treated as test case 255.
Set type="perl" to write the test case as a perl script. It implies that
there's no memory debugging and valgrind gets shut off for this test.
@@ -314,8 +318,11 @@ Variables are substituted on the contents of the file as in the <command>
section.
</file>
<stdin>
<stdin [nonewline="yes"]>
Pass this given data on stdin to the tool.
If 'nonewline' is set, we will cut off the trailing newline of this given data
before comparing with the one actually received by the client
</stdin>
</client>

View File

@@ -27,7 +27,7 @@ EXTRA_DIST = ftpserver.pl httpserver.pl secureserver.pl runtests.pl getpart.pm \
FILEFORMAT README stunnel.pem memanalyze.pl testcurl.pl valgrind.pm ftp.pm \
sshserver.pl sshhelp.pm testcurl.1 runtests.1 $(HTMLPAGES) $(PDFPAGES) \
serverhelp.pm tftpserver.pl rtspserver.pl directories.pm symbol-scan.pl \
CMakeLists.txt mem-include-scan.pl valgrind.supp
CMakeLists.txt mem-include-scan.pl valgrind.supp http_pipe.py
# we have two variables here to make sure DIST_SUBDIRS won't get 'unit'
# added twice as then targets such as 'distclean' misbehave and try to
@@ -66,7 +66,7 @@ endif
perlcheck:
@if ! test -x "$(PERL)"; then echo "No perl!"; exit 2; fi
test: perhcheck all
test: perlcheck all
$(TEST)
quiet-test: perlcheck all

View File

@@ -61,13 +61,15 @@ test626 test627 test628 test629 test630 test631 test632 test633 test634 \
test635 test636 test637 test638 test639 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 \
test709 test710 test711 test712 \
\
test800 test801 test802 test803 test804 test805 test806 test807 test808 \
test809 \
\
test850 test851 test852 test853 test854 test855 test856 test857 \
\
test900 test901 test902 test903 test904 test905 test906 \
test900 test901 test902 test903 test904 test905 test906 test907 test908 \
test909 test910 test911 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -89,8 +91,9 @@ test1128 test1129 test1130 test1131 test1132 test1133 \
\
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 \
test1220 test1221 test1222 test1223 \
test1216 test1217 test1218 test1219 \
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
test1228 test1229 test1230 \
\
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
@@ -103,13 +106,13 @@ test1356 test1357 test1358 test1359 test1360 test1361 test1362 test1363 \
test1364 test1365 test1366 test1367 test1368 test1369 test1370 test1371 \
test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 \
test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 \
test1388 test1389 test1390 test1391 test1392 test1393 \
test1388 test1389 test1390 test1391 test1392 test1393 test1394 test1396 \
\
test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
test1408 test1409 test1410 test1411 test1412 test1413 \
test1408 test1409 test1410 test1412 test1413 \
\
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
test1508 test1509 test1510 \
test1508 test1509 test1510 test1511 \
\
test1900 test1901 test1902 test1903 \
\

View File

@@ -39,7 +39,8 @@ FTP GET with type=A style ASCII URL using %20 codes
USER anonymous
PASS ftp@example.com
PWD
CWD /path with spaces
CWD /
CWD path with spaces
CWD and things2
EPSV
TYPE A

View File

@@ -874,7 +874,7 @@ crypto
HTTP proxy CONNECT auth Digest, large headers and data
</name>
<command>
http://test.remote.haxx.se.1060:%HTTPPORT/path/10600002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
http://test.remote.haxx.se.1060:8990/path/10600002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
</command>
</client>
@@ -884,17 +884,17 @@ http://test.remote.haxx.se.1060:%HTTPPORT/path/10600002 --proxy http://%HOSTIP:%
^User-Agent: curl/.*
</strip>
<protocol>
CONNECT test.remote.haxx.se.1060:%HTTPPORT HTTP/1.1
Host: test.remote.haxx.se.1060:%HTTPPORT
CONNECT test.remote.haxx.se.1060:8990 HTTP/1.1
Host: test.remote.haxx.se.1060:8990
Proxy-Connection: Keep-Alive
CONNECT test.remote.haxx.se.1060:%HTTPPORT HTTP/1.1
Host: test.remote.haxx.se.1060:%HTTPPORT
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1060:%HTTPPORT", response="e1fbed39c26f4efe284adc0e576ff638"
CONNECT test.remote.haxx.se.1060:8990 HTTP/1.1
Host: test.remote.haxx.se.1060:8990
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1060:8990", response="e1fbed39c26f4efe284adc0e576ff638"
Proxy-Connection: Keep-Alive
GET /path/10600002 HTTP/1.1
Host: test.remote.haxx.se.1060:%HTTPPORT
Host: test.remote.haxx.se.1060:8990
Accept: */*
</protocol>

View File

@@ -879,7 +879,7 @@ crypto
HTTP proxy CONNECT auth Digest, large headers and chunked data
</name>
<command>
http://test.remote.haxx.se.1061:%HTTPPORT/path/10610002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
http://test.remote.haxx.se.1061:8990/path/10610002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
</command>
</client>
@@ -889,17 +889,17 @@ http://test.remote.haxx.se.1061:%HTTPPORT/path/10610002 --proxy http://%HOSTIP:%
^User-Agent: curl/.*
</strip>
<protocol>
CONNECT test.remote.haxx.se.1061:%HTTPPORT HTTP/1.1
Host: test.remote.haxx.se.1061:%HTTPPORT
CONNECT test.remote.haxx.se.1061:8990 HTTP/1.1
Host: test.remote.haxx.se.1061:8990
Proxy-Connection: Keep-Alive
CONNECT test.remote.haxx.se.1061:%HTTPPORT HTTP/1.1
Host: test.remote.haxx.se.1061:%HTTPPORT
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1061:%HTTPPORT", response="4e23449fa93224834299e7282a70472c"
CONNECT test.remote.haxx.se.1061:8990 HTTP/1.1
Host: test.remote.haxx.se.1061:8990
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1061:8990", response="4e23449fa93224834299e7282a70472c"
Proxy-Connection: Keep-Alive
GET /path/10610002 HTTP/1.1
Host: test.remote.haxx.se.1061:%HTTPPORT
Host: test.remote.haxx.se.1061:8990
Accept: */*
</protocol>

49
tests/data/test1219 Normal file
View File

@@ -0,0 +1,49 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
</keywords>
</info>
# Server-side
<reply>
<data>
data
to
see
that FTP
works
so does it?
</data>
<servercmd>
REPLY welcome 230 welcome without password
</servercmd>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP with no user+password required (230 response)
</name>
<command>
ftp://%HOSTIP:%FTPPORT/1219
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
PWD
EPSV
TYPE I
SIZE 1219
RETR 1219
QUIT
</protocol>
</verify>
</testcase>

49
tests/data/test1224 Normal file
View File

@@ -0,0 +1,49 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
</keywords>
</info>
# Server-side
<reply>
<data>
data
to
see
that FTP
works
so does it?
</data>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP fetch a file from the root directory
</name>
<command>
ftp://%HOSTIP:%FTPPORT//1224
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
CWD /
EPSV
TYPE I
SIZE 1224
RETR 1224
QUIT
</protocol>
</verify>
</testcase>

57
tests/data/test1225 Normal file
View File

@@ -0,0 +1,57 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
</keywords>
</info>
# Server-side
<reply>
<data>
data
to
see
that FTP
works
so does it?
</data>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP fetch two files using absolute paths
</name>
<command>
ftp://%HOSTIP:%FTPPORT//foo/1225 ftp://%HOSTIP:%FTPPORT//foo/bar/1225
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
CWD /
CWD foo
EPSV
TYPE I
SIZE 1225
RETR 1225
CWD /
CWD /
CWD foo
CWD bar
EPSV
SIZE 1225
RETR 1225
QUIT
</protocol>
</verify>
</testcase>

49
tests/data/test1226 Normal file
View File

@@ -0,0 +1,49 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
</keywords>
</info>
# Server-side
<reply>
<data>
data
to
see
that FTP
works
so does it?
</data>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP fetch a file from the root directory with singlecwd
</name>
<command>
ftp://%HOSTIP:%FTPPORT//1226 --ftp-method singlecwd
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
CWD /
EPSV
TYPE I
SIZE 1226
RETR 1226
QUIT
</protocol>
</verify>
</testcase>

48
tests/data/test1227 Normal file
View File

@@ -0,0 +1,48 @@
<testcase>
<info>
<keywords>
FTP
PASV
RETR
</keywords>
</info>
# Server-side
<reply>
<data>
data
to
see
that FTP
works
so does it?
</data>
</reply>
# Client-side
<client>
<server>
ftp
</server>
<name>
FTP fetch a file from the root directory with nocwd
</name>
<command>
ftp://%HOSTIP:%FTPPORT//1227 --ftp-method nocwd
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<protocol>
USER anonymous
PASS ftp@example.com
PWD
EPSV
TYPE I
SIZE /1227
RETR /1227
QUIT
</protocol>
</verify>
</testcase>

54
tests/data/test1228 Normal file
View File

@@ -0,0 +1,54 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
cookies
cookie path
</keywords>
</info>
<reply>
<data>
HTTP/1.1 200 OK
Date: Tue, 25 Sep 2001 19:37:44 GMT
Set-Cookie: path1=root; domain=.example.fake; path=/;
Set-Cookie: path2=depth1; domain=.example.fake; path=/hoge;
Content-Length: 34
This server says cookie path test
</data>
</reply>
# Client-side
<client>
<server>
http
</server>
<name>
HTTP cookie path match
</name>
<command>
http://example.fake/hoge/1228 http://example.fake/hogege/ -b nonexisting -x %HOSTIP:%HTTPPORT
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET http://example.fake/hoge/1228 HTTP/1.1
Host: example.fake
Accept: */*
Proxy-Connection: Keep-Alive
GET http://example.fake/hogege/ HTTP/1.1
Host: example.fake
Accept: */*
Proxy-Connection: Keep-Alive
Cookie: path1=root
</protocol>
</verify>
</testcase>

82
tests/data/test1229 Normal file
View File

@@ -0,0 +1,82 @@
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP Digest auth
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
Content-Type: text/html; charset=iso-8859-1
Content-Length: 26
This is not the real page
</data>
# This is supposed to be returned when the server gets a
# Authorization: Digest line passed-in from the client
<data1000>
HTTP/1.1 200 OK swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
Content-Type: text/html; charset=iso-8859-1
Content-Length: 23
This IS the real page!
</data1000>
<datacheck>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
Content-Type: text/html; charset=iso-8859-1
Content-Length: 26
HTTP/1.1 200 OK swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
Content-Type: text/html; charset=iso-8859-1
Content-Length: 23
This IS the real page!
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
crypto
</features>
<name>
HTTP with Digest authorization with user name needing escape
</name>
<command>
http://%5cuser%22:password@%HOSTIP:%HTTPPORT/1229 --digest
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1229 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
GET /1229 HTTP/1.1
Authorization: Digest username="\\user\"", realm="testrealm", nonce="1053604145", uri="/1229", response="f2694d426040712584c156d3de72b8d6"
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

79
tests/data/test1230 Normal file
View File

@@ -0,0 +1,79 @@
<testcase>
<info>
<keywords>
HTTP
HTTP CONNECT
IPv6
</keywords>
</info>
#
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Content-Length: 9
mooooooo
</data>
<connect>
HTTP/1.1 200 welcome dear
Date: Thu, 09 Nov 2010 14:49:00 GMT
Content-Length: 0
</connect>
<datacheck>
HTTP/1.1 200 welcome dear
Date: Thu, 09 Nov 2010 14:49:00 GMT
Content-Length: 0
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Content-Length: 9
mooooooo
</datacheck>
</reply>
#
# Client-side
<client>
<features>
ipv6
</features>
<server>
http-proxy
http-ipv6
http
</server>
<name>
HTTP CONNECT to IPv6 numerical address
</name>
# 0x4ce == 1230, the test number
<command>
-g http://[1234:1234:1234::4ce]:%HTTPPORT/wanted/page/1230 -p -x %HOSTIP:%HTTPPORT
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
CONNECT [1234:1234:1234::4ce]:%HTTPPORT HTTP/1.1
Host: [1234:1234:1234::4ce]:%HTTPPORT
Proxy-Connection: Keep-Alive
GET /wanted/page/1230 HTTP/1.1
Host: [1234:1234:1234::4ce]:8990
Accept: */*
</protocol>
</verify>
</testcase>

View File

@@ -29,10 +29,10 @@ http-proxy
SMTP send tunneled trough HTTP proxy
</name>
<stdin>
From: different
To: another
body
From: different
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
@@ -54,11 +54,10 @@ DATA
QUIT
</protocol>
<upload>
From: different
To: another
body
From: different
To: another
body
.
</upload>
<proxy>

30
tests/data/test1394 Normal file
View File

@@ -0,0 +1,30 @@
<testcase>
<info>
<keywords>
unittest
</keywords>
</info>
#
# Client-side
<client>
<server>
none
</server>
<features>
unittest
</features>
<name>
unit test for parse_cert_parameter()
</name>
<tool>
unit1394
</tool>
</client>
<verify>
<stdout mode="text">
</stdout>
</verify>
</testcase>

27
tests/data/test1396 Normal file
View File

@@ -0,0 +1,27 @@
<testcase>
<info>
<keywords>
unittest
curl_easy_escape
curl_easy_unescape
</keywords>
</info>
#
# Client-side
<client>
<server>
none
</server>
<features>
unittest
</features>
<name>
curl_easy_escape and curl_easy_unescape
</name>
<tool>
unit1310
</tool>
</client>
</testcase>

View File

@@ -23,10 +23,10 @@ smtp
SMTP
</name>
<file name="log/test1406.eml">
From: different
To: another
body
From: different
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
@@ -38,18 +38,17 @@ smtp://%HOSTIP:%SMTPPORT/user --mail-rcpt 1406@foo --mail-rcpt 1406@foobar.examp
<verify>
<protocol>
EHLO user
MAIL FROM:<1406@from> SIZE=34
MAIL FROM:<1406@from> SIZE=38
RCPT TO:<1406@foo>
RCPT TO:<1406@foobar.example>
DATA
QUIT
</protocol>
<upload>
From: different
To: another
body
From: different
To: another
body
.
</upload>
<file name="log/test1406.c" mode="text">
@@ -70,7 +69,7 @@ int main(int argc, char *argv[])
slist1 = curl_slist_append(slist1, "1406@foobar.example");
hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)34);
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_HEADER, 1L);
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);

62
tests/data/test1511 Normal file
View File

@@ -0,0 +1,62 @@
<testcase>
<info>
<keywords>
HTTP
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 200
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fakem
Last-Modified: Mon, 22 Apr 2013 17:45:05 GMT
Content-Type: text/html
Content-Length: 12
Connection: close
Hello World
</data>
<datacheck>
HTTP/1.1 200
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fakem
Last-Modified: Mon, 22 Apr 2013 17:45:05 GMT
Content-Type: text/html
Content-Length: 12
Connection: close
HTTP/1.1 200
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fakem
Last-Modified: Mon, 22 Apr 2013 17:45:05 GMT
Content-Type: text/html
Content-Length: 12
Connection: close
Hello World
</datacheck>
</reply>
# Client-side
<client>
<server>
http
</server>
<features>
http
</features>
<tool>
lib1511
</tool>
<name>
HTTP GET time conditions in repeated requests
</name>
<command>
http://%HOSTIP:%HTTPPORT/1511
</command>
</client>
</testcase>

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