Compare commits

...

508 Commits

Author SHA1 Message Date
Daniel Stenberg
0966b324d9 RELEASE-NOTES: synced with c0ef05e67
... for the pending 7.34.0 release

Upped the contributor count
2013-12-16 22:54:00 +01:00
Daniel Stenberg
c0ef05e675 THANKS: add contributors from 7.34.0 release
24 new great friends
2013-12-16 22:53:20 +01:00
Daniel Stenberg
1dc43de0dc gtls: respect *VERIFYHOST independently of *VERIFYPEER
Security flaw CVE-2013-6422

This is conceptually the same problem and fix that 3c3622b6 brought to the
OpenSSL backend and that resulted in CVE-2013-4545.

This version of the problem was independently introduced to the GnuTLS
backend with commit 59cf93cc, present in the code since the libcurl
7.21.4 release.

Advisory: http://curl.haxx.se/docs/adv_20131217.html
Bug: http://curl.haxx.se/mail/lib-2013-11/0214.html
Reported-by: Marc Deslauriers
2013-12-16 22:47:31 +01:00
Daniel Stenberg
8a8f9a5d57 curl.1 document -J doesn't %-decode
...also added as KNOWN_BUG #87 with reference to bug #1294
2013-12-15 23:38:37 +01:00
Daniel Stenberg
be28223f35 multi: add timer inaccuracy margin to timeout/connecttimeout
Since all systems have inaccuracy in the timeout handling it is
imperative that we add an inaccuracy margin to the general timeout and
connecttimeout handling with the multi interface. This way, when the
timeout fires we should be fairly sure that it has passed the timeout
value and will be suitably detected.

For cases where the timeout fire before the actual timeout, we would
otherwise consume the timeout action and still not run the timeout code
since the condition wasn't met.

Reported-by: He Qin
Bug: http://curl.haxx.se/bug/view.cgi?id=1298
2013-12-15 22:53:41 +01:00
Daniel Stenberg
8e2d73bbde RELEASE-NOTES: synced with dd4d9ea542 2013-12-14 23:22:52 +01:00
Daniel Stenberg
dd4d9ea542 curl_easy_setopt: clarify some USERPWD and PROXYUSERPWD details 2013-12-14 23:09:05 +01:00
Daniel Stenberg
169fedbdce login options: remove the ;[options] support from CURLOPT_USERPWD
To avoid the regression when users pass in passwords containing semi-
colons, we now drop the ability to set the login options with the same
options. Support for login options in CURLOPT_USERPWD was added in
7.31.0.

Test case 83 was modified to verify that colons and semi-colons can be
used as part of the password when using -u (CURLOPT_USERPWD).

Bug: http://curl.haxx.se/bug/view.cgi?id=1311
Reported-by: Petr Bahula
Assisted-by: Steve Holme
Signed-off-by: Daniel Stenberg <daniel@haxx.se>
2013-12-14 22:40:37 +01:00
Steve Holme
32b9c30e67 imap: Fixed exclude of clear text when using auth=* in commit 75cd7fd667
It is not 100% clear whether * should include clear text LOGIN or not
from RFC-5092, however, including it is then consistent with current
POP3 behaviour where clear text, APOP or SASL may be chosen.
2013-12-14 12:24:17 +00:00
Steve Holme
75cd7fd667 imap: Fixed incorrect fallback to clear text authentication
If a specific SASL authentication mechanism was requested by the user
as part of the login options but wasn't supported by the server then
curl would fallback to clear text, when it shouldn't, rather than
reporting "No known authentication mechanisms supported" as the POP3
and SMTP protocols do.
2013-12-13 23:15:43 +00:00
Eric Lubin
7246dffff5 parsedate: avoid integer overflow
In C, signed integer overflow is undefined behavior. Thus, the compiler
is allowed to assume that it will not occur. In the check for an
overflow, the developer assumes that the signed integer of type time_t
will wrap around if it overflows. However, this behavior is undefined in
the C standard. Thus, when the compiler sees this, it simplifies t +
delta < t to delta < 0. Since delta > 0 and delta < 0 can't both be
true, the entire if statement is optimized out under certain
optimization levels. Thus, the parsedate function would return
PARSEDATE_OK with an undefined value in the time, instead of return -1 =
PARSEDATE_FAIL.
2013-12-11 16:32:21 +01:00
Daniel Stenberg
41d21e460f parseconfig: warn if unquoted white spaces are detected
Commit 0db811b6 made some existing config files pass on unexpected
values to libcurl that made it somewhat hard to track down what was
really going on.

This code detects unquoted white spaces in the parameter when parsing a
config file as that would be one symptom and it is generally a bad
syntax anyway.
2013-12-09 23:30:09 +01:00
Daniel Stenberg
aadca7f418 RELEASE-NOTES: recount contributors and libcurl options 2013-12-09 11:56:01 +01:00
Daniel Stenberg
3905bd637d RELEASE-NOTES: synced with c4f46e97ca 2013-12-07 22:52:31 +01:00
James Dury
c4f46e97ca TFTP: let tftp_multi_statemach()'s return codes through
It would otherwise always clobber the return code with new function
calls and it couldn't return timeout etc.

Bug: http://curl.haxx.se/bug/view.cgi?id=1310
2013-12-07 15:53:08 +01:00
Melissa Mears
bd3ca6630a darwinssl: Fix #if 10.6.0 for SecKeychainSearch
The comment here says that SecKeychainSearch causes a deprecation
warning when used with a minimum Mac OS X SDK version of 10.7.0, which
is correct.  However, the #if guard did not match.  It was intended to
only use the code if 10.6.0 support was enabled, but it had 10.7.0
instead.  This caused a warning if the minimum was exactly 10.7.0.
2013-12-07 00:10:04 -06:00
Christian Weisgerber
92e607abfa curl.h: <sys/select.h> for OpenBSD
curl.h should also include <sys/select.h> on OpenBSD to reliably
pull in select().  Typically, including <sys/time.h> will be enough,
but not if strict standards-compliance is requested (e.g. by defining
_XOPEN_SOURCE).
2013-12-06 13:28:27 +01:00
Daniel Stenberg
ef118c13ba digest: fix CURLAUTH_DIGEST_IE
The URI that is passed in as part of the Authorization: header needs to
be cut off at '?' if CURLAUTH_DIGEST_IE is set. Previously the code only
did when calculating the MD5sum.

Bug: http://curl.haxx.se/bug/view.cgi?id=1308
Patched-by: Sergey Tatarincev
2013-12-04 23:08:17 +01:00
Daniel Stenberg
1cf71bd76e Curl_is_connected: use proxy name in error message when proxy is used
(bug introduced in 255826c4, never present in a release)

Reported-by: Dima Tisnek
Bug: http://curl.haxx.se/mail/lib-2013-12/0006.html
2013-12-04 22:51:37 +01:00
Steve Holme
2c0ecac9d3 imap/pop3: Post graceful cancellation consistency changes 2013-12-04 20:19:36 +00:00
Melissa Mears
b0b5b51193 pop3: Fix POP3_TYPE_ANY signed compilation warning
POP3_TYPE_ANY, or ~0, is written to pop3c->preftype in lib/pop3c.c, an
unsigned int variable.  The result of ~0 is -1, which caused a warning
due to writing a negative number to an unsigned variable.  To fix this,
make the expression ~0U so that its value is considered the unsigned
number UINT_MAX which is what SASL_AUTH_ANY does in curl_sasl.h.
2013-12-04 20:18:44 +00:00
Kamil Dudka
ff9b66a8d4 tool_metalink: do not use HAVE_NSS_INITCONTEXT
... no longer provided by the configure script
2013-12-02 17:03:23 +01:00
Kamil Dudka
e221b55f67 nss: make sure that 'sslver' is always initialized 2013-12-02 16:09:12 +01:00
Kamil Dudka
865666afca nss: unconditionally require NSS_InitContext()
... since we depend on NSS 3.14+ because of SSL_VersionRangeSet() anyway
2013-12-02 15:00:13 +01:00
Kamil Dudka
7fc9325a52 nss: allow to use TLS > 1.0 if built against recent NSS
Bug: http://curl.haxx.se/mail/lib-2013-11/0162.html
2013-12-02 15:00:13 +01:00
Kamil Dudka
4fb8241add nss: put SSL version selection into separate fnc 2013-12-02 15:00:13 +01:00
Kamil Dudka
30e7e7552b nss: use a better API for controlling SSL version
This change introduces a dependency on NSS 3.14+.
2013-12-02 15:00:13 +01:00
Patrick Monnerat
f58f843f66 OS400: sync wrappers and RPG binding. 2013-12-02 14:33:51 +01:00
Steve Holme
d92de3a7e9 multi.c: Fixed compilation warning
warning: declaration of 'pipe' shadows a global declaration
2013-12-01 20:22:57 +00:00
Steve Holme
fe7fc61c6e RELEASE-NOTES: Synced with ad3836448e 2013-12-01 16:51:32 +00:00
Steve Holme
ad3836448e base64: Corrected typo from commit f3ee587775 2013-12-01 16:43:57 +00:00
Steve Holme
f3ee587775 base64: Post extended extended validation tidy up
Reduced the separate processing of the last quantum to be performed in
the main decoding loop and renamed some variables for consistency.
2013-12-01 13:59:47 +00:00
Steve Holme
c92c30edbd base64: Extended validation to look for invalid characters
Extended the basic validation in commit e17c1b25bc to return a
failure when invalid base64 characters are included.
2013-12-01 11:12:23 +00:00
Steve Holme
4d10f48629 base64: Post basic validation tidy up
Due to the length checks introduced in commit e17c1b25bc there is no
need to allow for extra space in the output buffer for a non-padded last
quantum.
2013-11-30 19:14:29 +00:00
Steve Holme
dc68120e63 curl_easy_getinfo: Post CURLINFO_TLS_SESSION tidy up
1) Renamed curl_tlsinfo to curl_tlssessioninfo as discussed on the
mailing list.
2) Renamed curl_ssl_backend to curl_sslbackend so it doesn't follow our
function naming convention.
3) Updated sessioninfo.c example accordingly.
2013-11-30 11:08:56 +00:00
Daniel Stenberg
0db811b69b parseconfig: dash options can't specified with colon or equals
Bug: http://curl.haxx.se/bug/view.cgi?id=1297
Reported-by: Michael Osipov
2013-11-29 15:17:08 +01:00
Daniel Stenberg
d81cbbcc2c curl.1: -G also takes --data-urlencode data 2013-11-29 15:10:53 +01:00
Daniel Stenberg
0dd6522036 globbing: curl glob counter mismatch with {} list use
The "fixed string" function wrongly bumped the "urlnum" counter which
made curl output the total number of URLs wrong when using
{one,two,three} lists in globs.

Reported-by: Michael-O
Bug: http://curl.haxx.se/bug/view.cgi?id=1305
2013-11-28 23:31:31 +01:00
Christian Grothoff
889cb9c982 sessioninfo.c: Added sample code for CURLINFO_TLS_SESSION
Added a simple example to show how one can use CURLINFO_TLS_SESSION for
obtaining extensive TLS certificate information.
2013-11-28 07:05:07 +00:00
Steve Holme
26ff1ea6c3 multi.c: Fixed compilation error introduced in commit a900d45489
Systems that define SIGPIPE_VARIABLE as a noop would not compile as
restore_pipe was defined afterwards.
2013-11-27 23:45:45 +00:00
Christian Grothoff
59f1209fad curl_easy_getopt: Handle API violation gracefully
This fixes a NULL dereference in the case where the client asks for
CURLINFO_TLS_SESSION data after the (TLS) session has already been
destroyed (i.e. curl_easy_perform has already completed for this
handle). Instead of crashing, we now return a CURLSSLBACKEND_NONE
error.
2013-11-27 23:35:34 +00:00
Steve Holme
7b9365c65f KNOWN_BUGS: #86: Disconnect commands may not be sent by IMAP, POP3 and SMTP 2013-11-27 22:35:08 +00:00
Jeff King
a900d45489 curl_multi_cleanup: ignore SIGPIPE
This is an extension to the fix in 7d80ed64e4. We may
call Curl_disconnect() while cleaning up the multi handle,
which could lead to openssl sending packets, which could get
a SIGPIPE.

Signed-off-by: Jeff King <peff@peff.net>
2013-11-27 22:47:12 +01:00
Jeff King
e64f91feb7 sigpipe: factor out sigpipe_reset from easy.c
Commit 7d80ed64e4 introduced some helpers to handle
sigpipe in easy.c. However, that fix was incomplete, and we
need to add more callers in other files. The first step is
making the helpers globally accessible.

Since the functions are small and should generally end up
inlined anyway, we simply define them in the header as
static functions.

Signed-off-by: Jeff King <peff@peff.net>
2013-11-27 22:46:55 +01:00
Björn Stenberg
b2a55c8106 connect: Try next ip directly after immediate connect fail
This fixes a rare Happy Eyeballs bug where if the first IP family runs
out of addresses before the second-family-timer fires, and the second
IP family's first connect fails immediately, no further IPs of the
second family are attempted.
2013-11-27 22:26:43 +01:00
Daniel Stenberg
030a2b8cb8 hostip: don't prune DNS cache entries that are in use
When adding entries to the DNS cache with CURLOPT_RESOLVE, they are
marked 'inuse' forever to prevent them from ever being removed in normal
operations. Still, the code that pruned out-of-date DNS entries didn't
care for the 'inuse' struct field and pruned it anyway!

Reported-by: Romulo A. Ceccon
Bug: http://curl.haxx.se/bug/view.cgi?id=1303
2013-11-25 00:10:23 +01:00
Steve Holme
edce855943 RELEASE-NOTES: Synced with 35e476a3f6 2013-11-24 18:05:54 +00:00
Steve Holme
35e476a3f6 tests: Re-ordered test arguments to match other IMAP tests 2013-11-24 17:59:17 +00:00
Steve Holme
0434a19431 tests: Corrected login "username" authentication responses 2013-11-24 16:25:44 +00:00
Steve Holme
2ff0c6f5f3 tests: Added error code explanation comments 2013-11-24 12:35:45 +00:00
Steve Holme
8a94aedbd6 tests: Removed expected QUIT response from graceful cancellation tests
A failure during authentication, which is performed as part of the
CONNECT phrase (for IMAP, POP3 and SMTP) is considered by the multi-
interface as being closed prematurely (aka a dead connection). As such
these protocols cannot issue the relevant QUIT or LOGOUT command.

Temporarily fixed the test cases until we can fix this properly.
2013-11-24 11:03:40 +00:00
Steve Holme
95877cf8ae tests: Added SMTP graceful authentication cancellation tests 2013-11-24 10:37:41 +00:00
Steve Holme
d3325ae40a tests: Added POP3 graceful authentication cancellation tests 2013-11-24 10:37:30 +00:00
Steve Holme
23fabf8dea ftpserver.pl: Reworked fix from commit 7a36b2abc0 2013-11-23 22:14:34 +00:00
Steve Holme
7a36b2abc0 ftpserver.pl: Fixed unknown IMAP command "*" 2013-11-23 19:19:12 +00:00
Steve Holme
e1c255f388 ftpserver.pl: Fixed servercmd REPLY with * detection 2013-11-23 16:28:28 +00:00
Steve Holme
6d3c832a30 tests: Added IMAP graceful authentication cancellation tests 2013-11-23 15:03:18 +00:00
Steve Holme
7935478397 tests: Moved CR LF in URL tests to their respective protocol groups 2013-11-23 14:49:50 +00:00
Steve Holme
5ee64be9c6 smtp: Post SMTP command expansion tidy up
Removed unnecessary SMTP_STOP state changes on failure.

Removed hard return on failure in smtp_state_data_resp().
2013-11-23 09:35:44 +00:00
Steve Holme
9f18cf15d5 symbols-in-versions: Added missing CURLSSLBACKEND_* symbols 2013-11-22 13:22:18 +00:00
Steve Holme
bf05da183e symbols-in-versions: Fixed missing CURLINFO_TLS_SESSION 2013-11-22 07:30:00 +00:00
Christian Grothoff
2c04e8d80c curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals
Added new API for returning a SSL backend type and pointer, in order to
allow access to the TLS internals, that may then be used to obtain X509
certificate information for example.
2013-11-21 20:40:04 +00:00
Steve Holme
925df53580 RELEASE-NOTES: Synced with 8191800a0c 2013-11-17 16:55:56 +00:00
Steve Holme
8191800a0c smtp: Fixed space being sent in non --mail-rcpt based requests
Commands such as NOOP, RSET and HELP would be sent with a space at the
end of the command, for example: "NOOP ".
2013-11-17 16:39:02 +00:00
Steve Holme
2165298fe6 tests: Added SMTP NOOP and RSET tests 2013-11-17 12:52:42 +00:00
Steve Holme
e885dc85a1 test928: Corrected typo in expected data from commit df58084695 2013-11-17 12:49:10 +00:00
Steve Holme
df58084695 tests: Added SMTP HELP test 2013-11-17 10:11:27 +00:00
Steve Holme
3c8c9b2779 smtp: Changed the default command to HELP when no options are specified
Otherwise a NOOP operation would be performed which a) only returns a
single line response and not a multiline response where -I needs to be
used, and b) provides an inconsistent user experience compared to that
of the POP3 and IMAP protocols.
2013-11-17 10:09:07 +00:00
Steve Holme
b27dc009cf smtp:Fixed memory leak from commit dac01ff6d7
The buffer allocated by smtp_parse_custom_request() was not freed.
2013-11-17 09:00:21 +00:00
Steve Holme
2c7a5578e1 connect: Close open but unconnected socket in singleipconnect()
singleipconnect() could return the file descriptor of an open socket
even though the function returned a CURLE_COULDNT_CONNECT error code
from commit ed1662c374 and 02fbc26d59.

This could cause tests 19, 704 and 1233 to fail on FreeBSD, AIX and
Solaris.
2013-11-17 00:27:18 +00:00
Steve Holme
b56d7cda74 tests: Added SMTP EXPN command test 2013-11-17 00:20:58 +00:00
Steve Holme
8896b56488 test926: Corrected unknown user reply from commit 0d735c29f9
The error code should not be sent as data as it isn't passed onto the
client as body data, so cannot be compared in the test suite against
expected data.
2013-11-16 20:33:08 +00:00
Steve Holme
0d735c29f9 tests: Corrected missing data reply sections from 3d50e91aee 2013-11-16 17:19:26 +00:00
Steve Holme
3d50e91aee tests: Added SMTP VRFY command tests 2013-11-16 12:20:22 +00:00
Steve Holme
0cbfe5a7d5 ftpserver.pl: Added support for new SMTP commands 2013-11-16 11:17:23 +00:00
Steve Holme
eedca5055e smtp: Fixed broken RCPT TO from commit 0ea4a80bb2 2013-11-15 22:20:56 +00:00
Daniel Stenberg
5d040632ac smtp_state_mail_resp: removed unused variable 'smtp' 2013-11-15 22:43:34 +01:00
Steve Holme
314c3b8480 DOCS: Updated curl_easy_setopt.3 following recent SMTP changes
* Added information about the verify and expand commands to
  CURLOPT_MAIL_RCPT.
* Reworked CURLOPT_CUSTOMREQUEST section, adding information about IMAP
  and SMTP custom commands.
2013-11-15 21:25:26 +00:00
Steve Holme
d630e1f389 DOCS: Updated manpage following recent SMTP modifications
* Added SMTP section to --request
* Expanded --mail-rcpt to describe the usage when using the verify and
  expand commands.
2013-11-15 21:23:56 +00:00
Steve Holme
0ea4a80bb2 smtp: Simplified the next RCPT TO logic 2013-11-15 21:05:45 +00:00
Steve Holme
ed4ce23c23 lib1507.c: Added missing set of CURLOPT_UPLOAD option
Although this option should have already been set, the SMTP module can
now download information from and send instructional commands to, an
SMTP server, requiring the option to be set in order to perform a mail
transfer.
2013-11-15 21:01:10 +00:00
Steve Holme
168aa59705 smtp.c: Fixed trailing whitespace 2013-11-15 20:43:04 +00:00
Steve Holme
f71b1ad908 smtp: Added support for VRFY and EXPN commands 2013-11-15 18:25:29 +00:00
Steve Holme
dac01ff6d7 smtp: Added support for NOOP and RSET commands 2013-11-15 16:14:01 +00:00
Steve Holme
4a9fe26837 smtp: Fixed handling of multiline server greeting responses
Incorrectly processed multiline server greeting responses as "wanted"
continue responses in smtp_endofresp(), from commit f16c0de4e9,
which in turn broke the SMTP server detection in the test suite,
because the EHLO command would not be sent.
2013-11-15 12:50:37 +00:00
Steve Holme
90ec8763a5 smtp.c: Fixed compilation error from commit f16c0de4e9
warning: unused variable 'smtpc'
2013-11-15 12:14:09 +00:00
Steve Holme
796333bc5e smtp: Fixed processing of more than one response when sent in same packet
Added a loop to smtp_statemach_act() in which Curl_pp_readresp() is
called until the cache is drained. Without this multiple responses
received in a single packet could result in a hang or delay.
2013-11-15 10:54:23 +00:00
Steve Holme
f16c0de4e9 smtp: Moved EHLO response handling to smtp_state_ehlo_resp()
Similar to the processing of untagged CAPABILITY responses in IMAP moved
the processing of multiline EHLO responses to smtp_state_ehlo_resp() and
introduced an internal response code of one to differentiate a multiline
continuation from the end of command. This also allows for the separate
processing of multiline responses from commands such as VRFY and EXPN.
2013-11-15 10:49:17 +00:00
Steve Holme
786cba1ada connect: Forgot to correct line endings before push in commit ed1662c374 2013-11-14 20:43:15 +00:00
Björn Stenberg
ed1662c374 connect: Return the socket descriptor even on fail
singleipconnect() did not return the open socket descriptor on some
errors, thereby sometimes causing a socket leak. This patch ensures
the socket is always returned.
2013-11-14 19:56:59 +00:00
Daniel Stenberg
1f0616ea1a configure: Fix test with -Werror=implicit-function-declaration
The ipv6 auto-detect test in configure returns a false negative when
CFLAGS contains -Werror=implicit-function-declaration. (I have been
using this flag to detect code issues that would result in SEGVs on
x86_64-cygwin.)

Patch-by: Yaakov Selkowitz
Bug: http://curl.haxx.se/bug/view.cgi?id=1304
2013-11-13 19:00:22 -08:00
Steve Holme
55250d2d02 test825: Corrected typo from commit b29217d0d6 2013-11-13 17:31:42 +00:00
Steve Holme
c5d73167a6 RELEASE-NOTES: Synced with bde901ad89 2013-11-13 10:12:01 +00:00
Steve Holme
bde901ad89 test922: Corrected title to match other OAuth 2.0 tests 2013-11-13 09:17:50 +00:00
Steve Holme
79c77f7c31 tests: Added IMAP OAuth 2.0 authentication with initial response test 2013-11-13 09:14:30 +00:00
Steve Holme
986c249f2f tests: Added IMAP NTLM authentication with initial response test 2013-11-13 09:14:10 +00:00
Steve Holme
3b8c3eb911 tests: Added IMAP login authentication with initial response test 2013-11-13 09:12:59 +00:00
Steve Holme
b29217d0d6 tests: Added IMAP plain authentication with initial response test 2013-11-13 09:12:32 +00:00
Steve Holme
534f90f9bf test873: Use proper padding in NTLM responses 2013-11-13 09:12:11 +00:00
Nick Zitzmann
dbe228353d darwinssl: check for SSLSetSessionOption() presence when toggling BEAST
Even though this is only a formality (since not many people build on
Mavericks while targeting Leopard), since we still support Leopard
at the earliest, we might as well be pedantic.
2013-11-12 20:26:20 -06:00
Nick Zitzmann
bf77101e5c darwinssl: PKCS#12 import feature now requires Lion or later
It turns out that some of the constants necessary to make this feature
work are missing from Snow Leopard's Security framework even though
they are defined in the headers.

Bug: http://curl.haxx.se/mail/lib-2013-11/0076.html
Reported by: myriachan
2013-11-12 20:18:04 -06:00
Steve Holme
2ea9a125a6 tests: Added POP3 OAuth 2.0 authentication with initial response test 2013-11-13 00:29:05 +00:00
Steve Holme
58a00d6d9f tests: Added POP3 NTLM authentication with initial response test 2013-11-13 00:24:06 +00:00
Steve Holme
57a27528e6 tests: Added POP3 login authentication with initial response test 2013-11-13 00:11:19 +00:00
Steve Holme
632c1edd06 tests: Added POP3 plain authentication with initial response test 2013-11-13 00:07:02 +00:00
Steve Holme
434bc09263 TODO: Added auth= in URLs to the wish list for HTTP 2013-11-12 20:32:25 +00:00
Steve Holme
f2584627c8 curl_easy_setopt: Added the ability to set the login options separately
Rather than set the authentication options as part of the login details
specified in the URL, or via the older CURLOPT_USERPWD option, added a
new libcurl option to allow the login options to be set separately.
2013-11-12 19:08:55 +00:00
Daniel Stenberg
6901861fc9 curl.1: mention that -O does no URL decoding 2013-11-12 09:28:07 -08:00
Tomas Hoger
d7d8a8f922 curl_easy_setopt.3: clarify CURLOPT_SSL_VERIFYHOST documentation
- better describe what happens when 1 is specified as parameter
- clarify what "is ignored" means for NSS builds
2013-11-12 17:03:13 +01:00
Steve Holme
c19cfb79db runtests.pl: Added SSPI detection 2013-11-12 12:48:28 +00:00
Steve Holme
65ce9b6d6c multi: Small code tidy up to avoid hard return 2013-11-12 09:59:22 +00:00
Steve Holme
5f34a10445 tests: Updated CRAM-MD5 tests to use test user details 2013-11-12 09:46:30 +00:00
Björn Stenberg
fa1253aee1 multi: Set read socket when returning READSOCK(0)
This patch fixes and issue introduced in commit 7d7df83198, if the
tunnel state was TUNNEL_CONNECT, waitconnect_getsock() would return a
bitmask indicating a readable socket but never stored the socket in the
return array.
2013-11-11 23:41:44 +00:00
Daniel Stenberg
f833f54979 bump: next release will be 7.34.0
Due to all the news and changes.
2013-11-11 08:46:27 +01:00
Björn Stenberg
e7d77fb3ef connect: Close temporary sockets in conn_free()
The temporary sockets used for Happy Eyeballs were not closed properly,
if curl exited prematurely, which this patch fixes.
2013-11-10 22:49:56 +00:00
Steve Holme
c8e63f247a tests: Corrected titles of POP3 and SMTP OAuth 2.0 tests 2013-11-10 20:26:57 +00:00
Steve Holme
7396ad6e09 test823: Fixed expected authentication text from commit e10a26a9d6
Fixed authentication text due to incorrect digest-uri property.
2013-11-10 20:21:18 +00:00
Steve Holme
6d295f8d7d test821: Fixed expected authentication text from commit 2d5455feac 2013-11-10 20:17:30 +00:00
Steve Holme
5bd999d0c5 RELEASE-NOTES: Synced with 0f81fbe5da 2013-11-10 18:16:21 +00:00
Kim Vandry
0f81fbe5da ares: Fixed compilation under Visual Studio 2012 2013-11-10 17:37:32 +00:00
Steve Holme
9b67960421 tests: Added IMAP OAuth 2.0 authentication test 2013-11-10 17:04:32 +00:00
Steve Holme
e10a26a9d6 tests: Added IMAP DIGEST-MD5 authentication test 2013-11-10 16:53:58 +00:00
Steve Holme
7b68b58bc0 tests: Added IMAP NTLM authentication test 2013-11-10 16:44:19 +00:00
Steve Holme
2d5455feac tests: Added IMAP CRAM-MD5 authentication test 2013-11-10 16:42:21 +00:00
Steve Holme
ac05c80f19 test819: Fixed expected authentication text from commit 76f924131c 2013-11-10 16:24:38 +00:00
Steve Holme
460adfef93 ftpserver.pl: Reworked custom reply handling code
1) To fix issues with IMAP custom replies
2) So initial space is not required in IMAP display text
3) To be more readable and understandable
2013-11-10 15:18:04 +00:00
Steve Holme
c876f6ae6d ftpserver.pl: Reworked unrecognised command responses
As the IMAP regex could fail and $1 would not contain the command id
updated the unrecognised command response to be more generic and
realistic (like those used in the command handlers).

Additionally updated the POP3, SMTP and FTP responses.
2013-11-10 10:20:50 +00:00
Steve Holme
f49276bfcb ftpserver.pl: Fixed processing of IMAP authentication strings 2013-11-10 10:08:32 +00:00
Daniel Stenberg
d08ee3c83d cmake: fix Windows build with IPv6 support
Patch-by: "Z98"
2013-11-09 00:07:32 +01:00
Steve Holme
cf7008670b Revert "ftpserver.pl: Corrected logic from commit 27b7b1062f9d97"
This reverts commit 558034ab70 as it appears to break the auto
builds. More thought is required for this!
2013-11-06 12:31:46 +00:00
Steve Holme
558034ab70 ftpserver.pl: Corrected logic from commit 27b7b1062f 2013-11-06 09:52:24 +00:00
Steve Holme
27b7b1062f ftpserver.pl: Fixed IMAP cmdid being sent on custom responses 2013-11-06 07:19:01 +00:00
Steve Holme
af82661dbd tests: Added IMAP login authentication test 2013-11-05 23:48:16 +00:00
Steve Holme
76f924131c tests: Added IMAP plain authentication test 2013-11-05 23:48:01 +00:00
Steve Holme
98a5fdaf29 url.c: Very small amount of policing 2013-11-05 23:30:12 +00:00
Björn Stenberg
1ea05be46d url.c: Remove superfluous for loop
The reason for this loop's existence was removed in commit
02fbc26d59.
2013-11-05 23:15:33 +00:00
Daniel Stenberg
c9d8c00a41 KNOWN_BUGS: STARTTRANSFER for POST requests
added 85. Wrong STARTTRANSFER timer accounting for POST requests
2013-11-05 10:21:30 +01:00
Daniel Stenberg
5aa290f0f2 Curl_ssl_push_certinfo_len: don't %.*s non-zero-terminated string
Our own printf() replacement clearly can't properly handle %.*s with a
string that isn't zero terminated. Instead of fixing the printf code or
even figuring out what the proper posix behavior is, I reverted this
piece of the code back to the previous version where it does malloc +
memcpy instead.

Regression added in e839446c2a, released in curl 7.32.0.

Reported-by: Felix Yan
Bug: http://curl.haxx.se/bug/view.cgi?id=1295
2013-11-05 09:59:19 +01:00
Steve Holme
f0831f7931 RELEASE-NOTES: Synced with 7fc3b2ce38 2013-11-05 07:17:24 +00:00
Steve Holme
7fc3b2ce38 connect.h: Updated copyright year for last edit 2013-11-05 07:15:01 +00:00
Björn Stenberg
02fbc26d59 connect: Add connection delay to Happy Eyeballs.
This patch adds a 200ms delay between the first and second address
family socket connection attempts.

It also iterates over IP addresses in the order returned by the
system, meaning most dual-stack systems will try IPv6 first.

Additionally, it refactors the connect code, removing most code that
handled synchronous connects. Since all sockets are now non-blocking,
the logic can be made simpler.
2013-11-04 22:38:19 +01:00
Steve Holme
0074c9f5d1 winbind: Fixed ntlm_auth expecting eol following commit e17c1b25bc 2013-11-04 20:12:22 +00:00
Steve Holme
90acbfd52e nss.c: Fixed compilation warnings (Take Two)
nss.c:702: warning: pointer targets in passing argument 3 of
'Curl_extract_certinfo' differ in signedness

nss.c:702: warning: pointer targets in passing argument 4 of
'Curl_extract_certinfo' differ in signedness

Made sure the cast was correctly "unsigned char *" to "char *" and not
"unsigned char *" to "unsigned char *".
2013-11-04 14:17:11 +00:00
Steve Holme
989b28fe97 nss.c: Fixed compilation warnings
nss.c:700: warning: pointer targets in passing argument 3 of
'Curl_extract_certinfo' differ in signedness

nss.c:700: warning: pointer targets in passing argument 4 of
'Curl_extract_certinfo' differ in signedness
2013-11-04 00:38:58 +00:00
Steve Holme
aa61e14dc1 tests: Added test for IMAP NOOP command 2013-11-03 21:36:46 +00:00
Steve Holme
a84a09ad0b tests: Added test for IMAP COPY command 2013-11-03 21:36:11 +00:00
Steve Holme
66b8557aff tests: Disable IMAP CLOSE and EXPUNGE command tests
This is temporary until curl supports either multiple custom commands
or post-quote commands in IMAP.
2013-11-03 20:39:21 +00:00
Steve Holme
63cac69c2a tests: Added tests for IMAP CLOSE and EXPUNGE commands 2013-11-03 20:37:34 +00:00
Steve Holme
f77d9b6584 connect.c: Code policing on commit 5094bb53f4
No need for a rhs condition on a bitwise compare.
2013-11-03 19:53:58 +00:00
Steve Holme
2736b27df7 nss.c: Fixed compilation warnings
warning: implicit declaration of function 'Curl_extract_certinfo'
2013-11-03 16:36:51 +00:00
Steve Holme
297644fa70 x509asn1.c: Fixed compilation warnings
warning: declaration of 'chsize' shadows a global declaration
2013-11-03 16:24:17 +00:00
Steve Holme
0177f28c51 DOCS: Expanded --request description to include POP3 and IMAP details 2013-11-03 14:39:10 +00:00
Steve Holme
732d10ed6c tool_help: Updated --list-only description to include POP3 2013-11-03 13:55:22 +00:00
Steve Holme
526a1c3b45 DOCS: Updated --list-only description to include POP3
Additionally corrected typos in --oauth2-bearer protocol list.
2013-11-03 13:54:49 +00:00
Steve Holme
5b315a273e base64: Fixed compilation warnings when using Curl_base64_decode()
curl_sasl.c:294: warning: dereferencing type-punned pointer will break
strict-aliasing rules

getpart.c:201: warning: dereferencing type-punned pointer will break
strict-aliasing rules
2013-11-03 12:25:07 +00:00
Steve Holme
5094bb53f4 connect: Fixed "Whut?" no server connection failures
Introduced in commit 7d7df83198 curl would loop displaying "Whut?"
if it was trying to connect to an address and port that didn't have
anything listening on it.
2013-11-03 11:27:12 +00:00
Steve Holme
052f24c9b7 http: Post base64 decoding tidy up
Renamed copy_header_value() to Curl_copy_header_value() as this
function is now non static.

Simplified proxy flag in Curl_http_input_auth() when calling
sub-functions.

Removed unnecessary white space removal when using negotiate as it had
been missed in commit cdccb42267.
2013-11-03 10:17:26 +00:00
Daniel Stenberg
bce03fe144 glob_range: pass the closing bracket for a-z ranges
Regression since commit 5ca96cb844 (release in 7.33.0)

Reported-by: Marcin Gryszkalis
2013-11-03 10:08:10 +01:00
Steve Holme
9a1755264f getpart: Fixed base64 encoded parts following commit e17c1b25bc 2013-11-02 17:00:00 +00:00
Steve Holme
3b59696a93 http: Added proxy tunnel authentication message header value extraction
...following recent changes to Curl_base64_decode() rather than trying
to parse a header line for the authentication mechanisms which is CRLF
terminated and inline zero terminate it.
2013-11-02 11:18:39 +00:00
Steve Holme
cdccb42267 http: Added authentication message header value extraction
...following recent changes to Curl_base64_decode() rather than trying
to parse a header line for the authentication mechanisms which is CRLF
terminated and inline zero terminate it.
2013-10-31 19:15:33 +00:00
Daniel Stenberg
753d44fa00 curl_multi_wait: accept 0 from multi_timeout() as valid timeout
The code rejected 0 as a valid timeout while in fact the function could
indeed legitimately return that and it should be respected.

Reported-by: Bjorn Stenberg
2013-10-30 23:48:08 +01:00
Steve Holme
cfdfdcdd9d email: Corrected a couple of typos from commit aa0eaef483 2013-10-30 21:25:15 +00:00
Steve Holme
e232f5f3f9 TODO: Removed the 'Graceful base64 decoding failure' sections
Updated following the recent changes to support graceful failures
during the authentication phrase.
2013-10-30 21:01:26 +00:00
Steve Holme
43400b4086 email: Post graceful SASL authentication cancellation tidy up 2013-10-30 20:58:24 +00:00
Kamil Dudka
8179354c2f tests: use proper padding in NTLM responses 2013-10-30 20:38:01 +00:00
Patrick Monnerat
f6c335d63f NSS: support for CERTINFO feature 2013-10-30 11:12:06 +01:00
Daniel Stenberg
2bd72fa61c base64: removed trailing white space
and updated copyright year
2013-10-30 09:11:10 +01:00
Steve Holme
e17c1b25bc base64: Added basic validation to base64 input string when decoding
A base64 string should be a multiple of 4 characters in length, not
contain any more than 2 padding characters and only contain padding
characters at the end of string. For example: Y3VybA==

Strings such as the following are considered invalid:

Y=   - Invalid length
Y==  - Invalid length
Y=== - More than two padding characters
Y=x= - Padding character contained within string
2013-10-30 07:31:22 +00:00
Daniel Stenberg
7d1eb66cd7 RELEASE-NOTES: synced with 255826c40f 2013-10-29 23:06:04 +01:00
Björn Stenberg
255826c40f bugfix: Don't block waiting for socket1 connect.
This patch fixes a bug in Happy Eyeballs where curl would wait for a
connect response from socket1 before checking socket2.

Also, it updates error messages for failed connections, showing the ip
addresses that failed rather than just the host name repeatedly.

Bug: http://curl.haxx.se/mail/lib-2013-10/0236.html
Reported-by: Paul Marks
2013-10-29 22:52:07 +01:00
Steve Holme
1d0eead969 sasl: Updated create_digest_md5_message() to use a dynamic buffer 2013-10-28 23:48:53 +00:00
Daniel Stenberg
8005e58983 SECURITY: "curl security for developers"
Describes our security process from a project and curl developer's
perspective.
2013-10-28 23:19:55 +01:00
Patrick Monnerat
5d415815df OS400: coding style standards 2013-10-28 12:00:22 +01:00
Steve Holme
f68559c086 email: Added support for cancelling NTLM authentication 2013-10-27 22:25:18 +00:00
Steve Holme
08f97f3b1d sasl: Removed unused variables from commit b87ba2c942 2013-10-27 17:04:56 +00:00
Steve Holme
b87ba2c942 email: Added support for cancelling DIGEST-MD5 authentication 2013-10-27 16:27:38 +00:00
Steve Holme
e7a2ba41e3 email: Corrected a couple of typos from 1e39b95682 2013-10-27 16:24:03 +00:00
Gisle Vanem
6fe619be7a docs/examples/httpput.c: fix build for MSVC
"Dan Fandrich" <dan@coneharvesters.com> wrote:

>> But I'm not sure <unistd.h> is needed at all.
>
> It's needed for close(2). But the only reason that's needed is because fstat
> is used instead of stat(2); if you fix that, then you could remove that
> include altogether.

Okay. I've tested the following with MSVC and MingW. htttput.c now
simply uses stat():
2013-10-27 15:48:57 +01:00
Steve Holme
1e39b95682 email: Added support for canceling CRAM-MD5 authentication 2013-10-27 12:42:30 +00:00
Björn Stenberg
8230af0b94 Typo fix in trynextip(). 2013-10-27 12:49:12 +01:00
Daniel Stenberg
1709e5e966 TODO: remove "Happy Eyeball dual stack connect"
... as it was just merged in commit 7d7df
2013-10-27 11:34:09 +01:00
Björn Stenberg
7d7df83198 Add "Happy Eyeballs" for IPv4/IPv6.
This patch invokes two socket connect()s nearly simultaneously, and
the socket that is first connected "wins" and is subsequently used for
the connection. The other is terminated.

There is a very slight IPv4 preference, in that if both sockets connect
simultaneously IPv4 is checked first and thus will win.
2013-10-27 11:19:53 +01:00
Steve Holme
7de4cc35f8 email: Added initial support for cancelling authentication
Should a client application fail to decode an authentication message
received from a server, or not support any of the parameters given by
the server in the message, then the authentication phrase should be
cancelled gracefully by the client rather than simply terminating the
connection.

The authentication phrase should be cancelled by simply sending a '*'
to the server, in response to erroneous data being received, as per
RFC-3501, RFC-4954 and RFC-5034.

This patch adds the necessary state machine constants and appropriate
response handlers in order to add this functionality for the CRAM-MD5,
DIGEST-MD5 and NTLM authentication mechanisms.
2013-10-27 09:17:03 +00:00
Steve Holme
aa0eaef483 email: Moved authentication message parsing into a separate function
...in preparation for upcoming modifications.
2013-10-27 09:04:59 +00:00
Steve Holme
9f503a254b ftp: Fixed compiler warning
warning: 'result' may be used uninitialized in this function
2013-10-27 00:00:01 +01:00
Daniel Stenberg
d44b014271 FTP: make the data connection work when going through proxy
This is a regression since the switch to always-multi internally
c43127414d.

Test 1316 was modified since we now clearly call the Curl_client_write()
function when doing the LIST transfer part and then the
handler->protocol says FTP and ftpc.transfertype is 'A' which implies
text converting even though that the response is initially a HTTP
CONNECT response in this case.
2013-10-26 23:33:06 +02:00
Steve Holme
469b423350 tool_help: Added login options to --user description 2013-10-26 20:11:48 +01:00
Steve Holme
0adad07690 email: Added references to SASL LOGIN authentication draft proposal 2013-10-26 14:35:27 +01:00
Steve Holme
e4670a1029 tests: Tidy up of SMTP and POP3 tests
Corrected line endings, RFC references and standardised on user names
and passwords used in the tests.
2013-10-26 13:50:08 +01:00
Steve Holme
1f0e50f2b9 tool_help: Added clarity to the --oauth2-bearer option
...as XOAUTH2 is the extended (or non-standard) SASL identifier and
OAuth 2 is the protocol name (and version).
2013-10-26 13:01:33 +01:00
Steve Holme
2766262a68 smtp: Fixed response code parsing for bad AUTH continuation responses
This workaround had been previously been implemented for IMAP and POP3
but not SMTP. Some of the recent test case additions implemented this
behaviour to emulate a bad server and the SMTP code didn't cope with it.
2013-10-26 11:09:31 +01:00
Steve Holme
bdb1f0e53d gskit.c: Code policing following commit 2cc9246477
Corrected 80 character line length error and pointer declarations (some
of which were previously incorrect)
2013-10-26 00:57:45 +01:00
Steve Holme
6e3613e6e6 test907: Corrected DIGEST-MD5 response given in commit 820ed48a00
As the URI, which is contained within the DIGEST-MD5 response, is
constructed from the service and realm, the encoded message differs
from that generated under POP3.
2013-10-26 00:24:45 +01:00
Steve Holme
1cb5150dba RELEASE-NOTES: Synced with d24b7953c2 2013-10-25 20:01:25 +01:00
Steve Holme
d24b7953c2 tests: Added SMTP OAUTH2 authentication with initial response test 2013-10-25 19:44:03 +01:00
Steve Holme
13db74ffc3 tests: Added SMTP NTLM authentication with initial response test 2013-10-25 19:40:23 +01:00
Steve Holme
98905aa2c5 tests: Added SMTP OAUTH2 authentication test 2013-10-25 19:34:05 +01:00
Steve Holme
820ed48a00 tests: Added SMTP DIGEST-MD5 authentication test 2013-10-25 19:31:51 +01:00
Steve Holme
973cc22529 tests: Regrouped SMTP authentication tests 2013-10-25 19:30:52 +01:00
Patrick Monnerat
2cc9246477 OS400: sync RPG wrapper, zlib support, fix header file names, ...
IFS compilation support, SSL GSKit backend by default, TLSv1.[12] support in
  GSKit for OS400 >= V7R1, no more tabs in make scripts.
2013-10-25 18:37:37 +02:00
Steve Holme
650036633f sasl: Fixed memory leak in OAUTH2 message creation 2013-10-24 00:16:59 +01:00
Steve Holme
78aee26be6 ftpserver.pl: Added support for empty pop3 authentication data 2013-10-23 22:19:42 +01:00
Daniel Stenberg
947d431d50 CURLOPT_RESOLVE: mention they don't time-out
Clarify in the documentation that DNS entries added with CURLOPT_RESOLVE
won't time-out.

Bug: http://curl.haxx.se/mail/lib-2013-10/0062.html
Reported-by: Romulo Ceccon
2013-10-23 23:15:36 +02:00
Steve Holme
58bd0148fb tests: Added POP3 OAUTH2 authentication test 2013-10-23 22:12:04 +01:00
Steve Holme
ca5c5be3e4 tests: Added empty response support to custom replies
...and fixed up test869 as DIGEST-MD transcript is as follows:

S: Challenge
C: Authentication String
S: Continue Response
C: Empty String
2013-10-23 22:05:22 +01:00
Daniel Stenberg
9bd37a6d27 sasl: fix compiler warning
error: unused variable 'table16'
2013-10-23 22:28:13 +02:00
Steve Holme
1be69159f3 tests: Added POP3 DIGEST-MD5 authentication test 2013-10-23 18:30:00 +01:00
Daniel Stenberg
a3da0a96e3 configure: check for long long when building with cyassl
cyassl/ctaocrypt/types.h needs SIZEOF_LONG_LONG

Reported-by: Chris Conlon
2013-10-22 22:55:48 +02:00
Daniel Stenberg
626f8a85f0 test1240: verify 867b52a7ac (glob ranges with text to the right) 2013-10-22 00:10:16 +02:00
Daniel Stenberg
867b52a7ac glob: fix regression from commit 5ca96cb844
Plain strings after glob ranges/lists weren't treated correctly but
caused broken URLs to get used.

Reported-by: Javier Barroso
2013-10-22 00:01:17 +02:00
Rémy Léone
be31924f8c Adding a .travis.yml file to use the travis-ci.org
From wikipedia:

Travis CI is a hosted, distributed continuous integration service used
to build and test projects hosted at GitHub.

Travis CI is configured by adding a file named .travis.yml, which is a
YAML format text file, to the root directory of the GitHub repository.

Travis CI automatically detects when a commit has been made and pushed
to a GitHub repository that is using Travis CI, and each time this
happens, it will try to build the project and run tests. This includes
commits to all branches, not just to the master branch. When that
process has completed, it will notify a developer in the way it has been
configured to do so — for example, by sending an email containing the
test results (showing success or failure), or by posting a message on an
IRC channel. It can be configured to run the tests on a range of
different machines, with different software installed (such as older
versions of a programming language, to test for compatibility).
2013-10-21 23:15:16 +02:00
Kamil Dudka
f70b2c77f4 ssh: initialize per-handle data in ssh_connect()
... if not already initialized.  This fixes a regression introduced by
commit 4ad8e142da, which caused test619
to intermittently fail on certain machines (namely Fedora build hosts).
2013-10-21 19:00:06 +02:00
Gisle Vanem
ae495ffcc3 curl.1: add missing exit-code
I noted a missing text for exit-code 89 in docs/curl.1
2013-10-20 23:57:24 +02:00
Daniel Stenberg
0fdfe82c6a cmake: unbreak for non-Windows platforms
Patch-by: Oliver Kuckertz
Bug: http://curl.haxx.se/bug/view.cgi?id=1292
2013-10-20 17:12:56 +02:00
Steve Holme
dead10b1b8 ftpserver.pl: Fixed syntax error from commit 5b31b38c27 2013-10-20 00:30:03 +01:00
Steve Holme
41d820d2c3 test866: Fixed user response from commit 7f7fbe7fbd 2013-10-19 21:43:20 +01:00
Steve Holme
5b31b38c27 ftpserver.pl: Fixed processing of POP3 authentication strings
...and corrected response when check fails from 500 to -ERR.
2013-10-19 20:39:18 +01:00
Steve Holme
39f4e4fafa tests: Added POP3 NTLM authentication test 2013-10-19 13:17:25 +01:00
Steve Holme
587811c0a6 tests: Added POP3 CRAM-MD5 authentication test 2013-10-19 12:57:25 +01:00
Steve Holme
7f7fbe7fbd tests: Added POP3 login authentication test 2013-10-19 12:42:25 +01:00
Steve Holme
9b1eb2b421 tests: Added POP3 plain authentication test 2013-10-19 12:31:55 +01:00
Steve Holme
1034aa6680 tests: Added POP3 APOP authentication test 2013-10-19 12:20:00 +01:00
Steve Holme
4be0af7f74 ftpserver.pl: Added support for APOP POP3 authentication 2013-10-19 10:38:19 +01:00
Steve Holme
72f850571d tests: Added POP3 RSET test 2013-10-19 00:10:29 +01:00
Steve Holme
e179d0eb12 RELEASE-NOTES: Synced with ce61510127 2013-10-18 19:54:30 +01:00
Steve Holme
ce61510127 email: Fixed QUIT / LOGOUT being sent when SSL connect fails 2013-10-18 19:28:20 +01:00
Kamil Dudka
86c64f3daf curl_sasl: initialize NSS before using crypto 2013-10-18 15:37:18 +02:00
Steve Holme
65e556d0ce SSL: Follow up work to commits 6a1363128f and 87861c9b0e
Changed the failure code when TLS v1.1 and v1.2 is requested but not
supported by older OpenSSL versions, following review from libcurl
peers, and reduced the number of required preprocessor if statements.
2013-10-17 19:57:26 +01:00
Steve Holme
6a1363128f SSL: Added unsupported cipher version check for OpenSSL
...with the use of CURL_SSLVERSION_TLSv1_1 and CURL_SSLVERSION_TLSv1_2
being conditional on OpenSSL v1.0.1 as the appropriate flags are not
supported under earlier versions.
2013-10-16 20:48:24 +01:00
Steve Holme
75b9b26465 DOCS: Added libcurl version number to CURLOPT_SSLVERSION 2013-10-16 20:18:18 +01:00
Steve Holme
2c84ffe154 SSL: Corrected version number for new symbols from commit ad34a2d5c8 2013-10-16 20:06:23 +01:00
Steve Holme
e7452415c5 SSL: Corrected typo from commit 87861c9b0e 2013-10-16 00:57:01 +01:00
Steve Holme
87861c9b0e SSL: Fixed OpenSSL builds prior to v1.0.1
Commit ad34a2d5c8 relies on definitions that are only present in
OpenSSL v1.0.1 and up. This quick fix allows the builds that use
older versions of OpenSSL to continue building.
2013-10-16 00:49:23 +01:00
Steve Holme
4d49ffe165 test906: Fixed failing test on some platforms
Bug: http://sourceforge.net/p/curl/bugs/1291
Reported-by: David Walser
2013-10-15 21:31:14 +01:00
Paul Donohue
f63603dec4 NSS: acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option 2013-10-15 21:50:22 +02:00
Tyler Hall
0218a737fe ssh: Handle successful SSH_USERAUTH_NONE
According to the documentation for libssh2_userauth_list(), a NULL
return value is not necessarily an error. You must call
libssh2_userauth_authenticated() to determine if the SSH_USERAUTH_NONE
request was successful.

This fixes a segv when using sftp on a server that allows logins with an
empty password. When NULL was interpreted as an error, it would
free the session but not flag an error since the libssh2 errno would be
clear. This resulted in dereferencing a NULL session pointer.

Signed-off-by: Tyler Hall <tylerwhall@gmail.com>
2013-10-15 20:53:09 +02:00
Ishan SinghLevett
18ca0aa984 usercertinmem: fix memory leaks 2013-10-15 20:48:22 +02:00
Dave Reisner
c4e6c33b13 build: distribute and install libcurl.m4 by default 2013-10-15 20:43:39 +02:00
Dave Reisner
d774802eec tool: use XFERFUNCTION to save some casts 2013-10-15 20:42:05 +02:00
Alessandro Ghedini
69c0d3fbc8 curl.1: fix typo conjuction -> conjunction 2013-10-15 20:37:13 +02:00
Daniel Stenberg
076726f141 curl: document the new --tlsv1.[012] options 2013-10-15 20:31:04 +02:00
Gergely Nagy
ad34a2d5c8 SSL: protocol version can be specified more precisely
CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2 enum values are added to force exact TLS version
(CURL_SSLVERSION_TLSv1 means TLS 1.x).

axTLS:
axTLS only supports TLS 1.0 and 1.1 but it cannot be set that only one
of these should be used, so we don't allow the new enum values.

darwinssl:
Added support for the new enum values.

SChannel:
Added support for the new enum values.

CyaSSL:
Added support for the new enum values.
Bug: The original CURL_SSLVERSION_TLSv1 value enables only TLS 1.0 (it
did the same before this commit), because CyaSSL cannot be configured to
use TLS 1.0-1.2.

GSKit:
GSKit doesn't seem to support TLS 1.1 and TLS 1.2, so we do not allow
those values.
Bugfix: There was a typo that caused wrong SSL versions to be passed to
GSKit.

NSS:
TLS minor version cannot be set, so we don't allow the new enum values.

QsoSSL:
TLS minor version cannot be set, so we don't allow the new enum values.

OpenSSL:
Added support for the new enum values.
Bugfix: The original CURL_SSLVERSION_TLSv1 value enabled only TLS 1.0,
now it enables 1.0-1.2.

Command-line tool:
Added command line options for the new values.
2013-10-15 20:26:47 +02:00
Nick Zitzmann
31e106c01c darwinssl: un-break iOS build after PKCS#12 feature added
SecPKCS12Import() returns a few errors that are enumerated in OS X's
headers but not in iOS' headers for some reason.
2013-10-14 18:03:32 -05:00
Daniel Stenberg
1dcc433661 bump: start working on 7.33.1 2013-10-14 23:11:20 +02:00
Daniel Stenberg
a106abee62 THANKS: added contributors from the 7.33.0 announcement 2013-10-14 23:10:35 +02:00
Daniel Stenberg
f77e89c5d2 RELEASE-NOTES: synced with 92cf6141ed 2013-10-13 23:24:21 +02:00
Daniel Stenberg
92cf6141ed curl: fix --oauth2-bearer in the --help output
After the option rename in 5df04bfafd
2013-10-13 23:21:12 +02:00
Daniel Stenberg
cf12d5b62f OpenSSL: improve the grammar of the language in 39beaa5ffb
Reported-by: Petr Pisar
2013-10-13 23:08:12 +02:00
Andrej E Baranov
39beaa5ffb OpenSSL: use failf() when subjectAltName mismatches
Write to CURLOPT_ERRORBUFFER information about mismatch alternative
certificate subject names.

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

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

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

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

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

Make sure HAVE_STRUCT_POLLFD is defined then.

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

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

For more information about the mechanism strings see:

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

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

For example:

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

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

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

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

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

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

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

CAPA "SIZE 1048576" 8BITMIME BINARYMIME

will populate the capabilities list with the following in:

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

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

Allows something like this:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Added test 1238 to verify.

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

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

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

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

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

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

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

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

For example:

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

Expected result: 300
Actual result: 255

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

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

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

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

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

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

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

Added test 1236 to verify.

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

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

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

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

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

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

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

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

This commit fixes three separate bug reports.

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

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

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

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

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

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

11
.travis.yml Normal file
View File

@@ -0,0 +1,11 @@
language: c
before_script:
- ./buildconf
compiler:
- clang
- gcc
notifications:
email: false

View File

@@ -108,7 +108,11 @@ if(NOT UNIX)
set(HAVE_IN_ADDR_T 0) set(HAVE_IN_ADDR_T 0)
set(HAVE_INET_NTOA_R_DECL 0) set(HAVE_INET_NTOA_R_DECL 0)
set(HAVE_INET_NTOA_R_DECL_REENTRANT 0) set(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
set(HAVE_GETADDRINFO 0) if(ENABLE_IPV6)
set(HAVE_GETADDRINFO 1)
else()
set(HAVE_GETADDRINFO 0)
endif()
set(STDC_HEADERS 1) set(STDC_HEADERS 1)
set(RETSIGTYPE_TEST 1) set(RETSIGTYPE_TEST 1)

View File

@@ -783,6 +783,17 @@ else()
set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT}) set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT})
endif() endif()
# TODO test which of these headers are required for the typedefs used in curlbuild.h
if(WIN32)
set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H})
else()
set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H})
set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H})
set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H})
endif()
set(CURL_PULL_STDINT_H ${HAVE_STDINT_H})
set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H})
include(CMake/OtherTests.cmake) include(CMake/OtherTests.cmake)
add_definitions(-DHAVE_CONFIG_H) add_definitions(-DHAVE_CONFIG_H)

View File

@@ -1,69 +1,71 @@
Curl and libcurl 7.32.0 Curl and libcurl 7.34.0
Public curl releases: 134 Public curl releases: 136
Command line options: 152 Command line options: 161
curl_easy_setopt() options: 199 curl_easy_setopt() options: 206
Public functions in libcurl: 58 Public functions in libcurl: 58
Known libcurl bindings: 42 Known libcurl bindings: 42
Contributors: 1049 Contributors: 1104
*** This release includes the following security fix:
krb4 support is up for removal. If you care about it at all, speak up o gtls: respect *VERIFYHOST independently of *VERIFYPEER [26]
on the curl-library list asap!
***
This release includes the following changes: This release includes the following changes:
o curl: allow timeouts to accept decimal values o SSL: protocol version can be specified more precisely [1]
o OS400: add slist and certinfo EBCDIC support o imap/pop3/smtp: Added graceful cancellation of SASL authentication
o OS400: new SSL backend GSKit o Add "Happy Eyeballs" for IPv4/IPv6 dual connect attempts
o CURLOPT_XFERINFOFUNCTION: introducing a new progress callback o base64: Added validation of base64 input strings when decoding [8]
o LIBCURL-STRUCTS: new document o curl_easy_setopt: Added the ability to set the login options separately
o smtp: Added support for additional SMTP commands
o curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals
o nss: allow to use TLS > 1.0 if built against recent NSS [18]
o SECURITY: added this document to describe our security processes [22]
o parseconfig: warn if unquoted white spaces are detected
This release includes the following bugfixes: This release includes the following bugfixes:
o dotdot: introducing dot file path cleanup [1] o darwinssl: un-break iOS build after PKCS#12 feature added
o docs: fix typo in curl_easy_getinfo manpage o tool: use XFERFUNCTION to save some casts [2]
o test1230: avoid using hard-wired port number o usercertinmem: fix memory leaks
o test1396: invoke the correct test tool o ssh: Handle successful SSH_USERAUTH_NONE [3]
o SIGPIPE: ignored while inside the library [2] o NSS: acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option [4]
o darwinssl: fix crash that started happening in Lion o test906: Fixed failing test on some platforms [5]
o OpenSSL: check for read errors, don't assume [3] o sasl: initialize NSS before using NTLM crypto
o c-ares: improve error message on failed resolve [4] o sasl: Fixed memory leak in OAUTH2 message creation
o printf: make sure %x are treated unsigned o imap/pop3/smtp: Fixed QUIT / LOGOUT being sent when SSL connect fails
o formpost: better random boundaries [5] o cmake: unbreak for non-Windows platforms [6]
o url: restore the functionality of 'curl -u :' [6] o ssh: initialize per-handle data in ssh_connect()
o curl.1: fix typo in --xattr description [7] o glob: fix broken URLs
o digest: improve nonce generation o configure: check for long long when building with cyassl
o configure: automake 1.14 compatibility tweak o CURLOPT_RESOLVE: mention they don't time-out [7]
o curl.1: document the --post303 option in the man page o docs/examples/httpput.c: fix build for MSVC
o curl.1: document the --sasl-ir option in the man page o FTP: make the data connection work when going through proxy
o setup-vms.h: sk_pop symbol tweak o NSS: support for CERTINFO feature
o tool_paramhlp: try harder to catch negatives o curl_multi_wait: accept 0 from multi_timeout() as valid timeout
o cmake: Fix for MSVC2010 project generation [8] o glob_range: pass the closing bracket for a-z ranges
o asyn-ares: Don't blank ares servers if none configured o tool_help: Updated --list-only description to include POP3
o curl_multi_wait: set revents for extra fds o Curl_ssl_push_certinfo_len: don't %.*s non-zero-terminated string [9]
o Reinstate "WIN32 MemoryTracking: track wcsdup() _wcsdup() and _tcsdup() o cmake: fix Windows build with IPv6 support [10]
o ftp_do_more: consider DO_MORE complete when server connects back [9] o ares: Fixed compilation under Visual Studio 2012 [11]
o curl_easy_perform: gradually increase the delay time [10] o curl_easy_setopt.3: clarify CURLOPT_SSL_VERIFYHOST documentation [12]
o curl: fix symbolic names for CURLUSESSL_* enum in --libcurl output o curl.1: mention that -O does no URL decoding [13]
o curl: fix upload of a zip file in OpenVMS [11] o darwinssl: PKCS#12 import feature now requires Lion or later [14]
o build: fix linking on Solaris 10 [12] o darwinssl: check for SSLSetSessionOption() presence when toggling BEAST
o curl_formadd: CURLFORM_FILECONTENT wrongly rejected some option combos [13] o configure: Fix test with -Werror=implicit-function-declaration [15]
o curl_formadd: fix file upload on VMS [14] o sigpipe: factor out sigpipe_reset from easy.c
o curl_easy_pause: on unpause, trigger mulit-socket handling [15] o curl_multi_cleanup: ignore SIGPIPE
o md5 & metalink: use better build macros on Apple operating systems [16] o globbing: curl glob counter mismatch with {} list use [16]
o darwinssl: fix build error in crypto authentication under Snow Leopard [16] o parseconfig: dash options can't specified with colon or equals [17]
o curl: make --progress-bar update the line less frequently [17] o digest: fix CURLAUTH_DIGEST_IE [19]
o configure: don't error out on variable confusions (CFLAGS, LDFLAGS etc) o curl.h: <sys/select.h> for OpenBSD [20]
o mk-ca-bundle: skip more untrusted certificates o darwinssl: Fix #if 10.6.0 for SecKeychainSearch
o formadd: wrong pointer for file name when CURLFORM_BUFFERPTR used [18] o TFTP: fix return codes for connect timeout [21]
o FTP: when EPSV gets a 229 but fails to connect, retry with PASV o login options: remove the ;[options] support from CURLOPT_USERPWD [23]
o mk-ca-bundle.1: don't install on make install [19] o imap: Fixed incorrect fallback to clear text authentication
o VMS: lots of updates and fixes of the build procedure o parsedate: avoid integer overflow
o global dns cache: didn't work (regression) o curl.1: document -J doesn't %-decode [25]
o global dns cache: fix memory leak o multi: add timer inaccuracy margin to timeout/connecttimeout [24]
o
This release includes the following known bugs: This release includes the following known bugs:
@@ -72,34 +74,42 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and This release would not have looked like this without help, code, reports and
advice from friends like these: advice from friends like these:
Alex Vinnik, Alessandro Ghedini, Nick Zitzmann, Kamil Dudka, Alessandro Ghedini, Andreas Rieke, Björn Stenberg, Chris Conlon,
Lluis Batlle i Rossell, Nach M. S., Kim Vandry, Ben Greear, Dan Fandrich, Christian Grothoff, Christian Weisgerber, Dave Reisner, David Walser,
Dave Reisner, Evgeny Turnaev, Guenter Knauf, John E. Malmberg, Marc Hoersken, Dima Tisnek, Fabian Keil, Felix Yan, Gergely Nagy, Gisle Vanem,
Patrick Monnerat, Sergei Nikulov, Yang Tse, Andreas Malzahn, Clemens Gruber, Ishan SinghLevett, James Dury, Javier Barroso, Jeff King, Kamil Dudka,
Jean-Noel Rouvignac, Markus Moeller, Fabian Keil, Dagobert Michelsen, Kim Vandry, Marcin Gryszkalis, Melissa Mears, Michael Osipov, Nick Zitzmann,
Byrial Jensen, Justin Karneges, Edward Rudd, Marc Doughty, Konstantin Isakov, Oliver Kuckertz, Patrick Monnerat, Paul Donohue, Paul Marks, Romulo A. Ceccon,
Rémy Léone, Sergey Tatarincev, Steve Holme, Tomas Hoger, Tyler Hall,
Yaakov Selkowitz, Eric Lubin, Petr Bahula, He Qin, Marc Deslauriers
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)
References to bug reports and discussions on issues: References to bug reports and discussions on issues:
[1] = http://curl.haxx.se/bug/view.cgi?id=1200 [1] = https://github.com/bagder/curl/pull/79
[2] = http://curl.haxx.se/bug/view.cgi?id=1180 [2] = http://curl.haxx.se/mail/lib-2013-10/0089.html
[3] = http://curl.haxx.se/bug/view.cgi?id=1249 [3] = http://curl.haxx.se/mail/lib-2013-10/0096.html
[4] = http://curl.haxx.se/bug/view.cgi?id=1191 [4] = http://curl.haxx.se/mail/lib-2013-10/0113.html
[5] = http://curl.haxx.se/bug/view.cgi?id=1251 [5] = http://sourceforge.net/p/curl/bugs/1291
[6] = http://curl.haxx.se/mail/archive-2013-06/0052.html [6] = http://sourceforge.net/p/curl/bugs/1292
[7] = http://curl.haxx.se/bug/view.cgi?id=1252 [7] = http://curl.haxx.se/mail/lib-2013-10/0062.html
[8] = http://curl.haxx.se/mail/lib-2013-07/0046.html [8] = http://curl.haxx.se/mail/lib-2013-10/0242.html
[9] = http://curl.haxx.se/mail/lib-2013-07/0115.html [9] = http://curl.haxx.se/bug/view.cgi?id=1295
[10] = http://curl.haxx.se/mail/lib-2013-07/0103.html [10] = http://sourceforge.net/p/curl/bugs/1064
[11] = http://curl.haxx.se/bug/view.cgi?id=496 [11] = http://curl.haxx.se/mail/lib-2013-11/0057.html
[12] = http://curl.haxx.se/bug/view.cgi?id=1217 [12] = https://github.com/bagder/curl/pull/83
[13] = http://curl.haxx.se/mail/lib-2013-07/0258.html [13] = http://sourceforge.net/p/curl/bugs/1299
[14] = http://curl.haxx.se/bug/view.cgi?id=758 [14] = http://curl.haxx.se/mail/lib-2013-11/0076.html
[15] = http://curl.haxx.se/mail/lib-2013-07/0239.html [15] = http://curl.haxx.se/bug/view.cgi?id=1304
[16] = http://curl.haxx.se/bug/view.cgi?id=1255 [16] = http://curl.haxx.se/bug/view.cgi?id=1305
[17] = http://curl.haxx.se/mail/archive-2013-07/0031.html [17] = http://curl.haxx.se/bug/view.cgi?id=1297
[18] = http://curl.haxx.se/bug/view.cgi?id=1262 [18] = http://curl.haxx.se/mail/lib-2013-11/0162.html
[19] = http://curl.haxx.se/mail/lib-2013-08/0057.html [19] = http://curl.haxx.se/bug/view.cgi?id=1308
[20] = http://curl.haxx.se/mail/lib-2013-12/0017.html
[21] = http://curl.haxx.se/bug/view.cgi?id=1310
[22] = http://curl.haxx.se/dev/security.html
[23] = http://curl.haxx.se/bug/view.cgi?id=1311
[24] = http://curl.haxx.se/bug/view.cgi?id=1298
[25] = http://curl.haxx.se/bug/view.cgi?id=1294
[26] = http://curl.haxx.se/docs/adv_20131217.html

View File

@@ -2619,48 +2619,49 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
fi fi
capath="$want_capath" capath="$want_capath"
ca="no" ca="no"
elif test "x$cross_compiling" != "xyes"; then else
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 first try autodetecting a CA bundle , then a CA path
dnl both autodetections can be skipped by --without-ca-* dnl both autodetections can be skipped by --without-ca-*
ca="no" ca="no"
capath="no" capath="no"
if test "x$want_ca" = "xunset"; then if test "x$cross_compiling" != "xyes"; then
dnl the path we previously would have installed the curl ca bundle dnl NOT cross-compiling and...
dnl to, and thus we now check for an already existing cert in that place dnl neither of the --with-ca-* options are provided
dnl in case we find no other if test "x$want_ca" = "xunset"; then
if test "x$prefix" != xNONE; then dnl the path we previously would have installed the curl ca bundle
cac="${prefix}/share/curl/curl-ca-bundle.crt" dnl to, and thus we now check for an already existing cert in that
else dnl place in case we find no other
cac="$ac_default_prefix/share/curl/curl-ca-bundle.crt" if test "x$prefix" != xNONE; then
fi cac="${prefix}/share/curl/curl-ca-bundle.crt"
else
cac="$ac_default_prefix/share/curl/curl-ca-bundle.crt"
fi
for a in /etc/ssl/certs/ca-certificates.crt \ for a in /etc/ssl/certs/ca-certificates.crt \
/etc/pki/tls/certs/ca-bundle.crt \ /etc/pki/tls/certs/ca-bundle.crt \
/usr/share/ssl/certs/ca-bundle.crt \ /usr/share/ssl/certs/ca-bundle.crt \
/usr/local/share/certs/ca-root.crt \ /usr/local/share/certs/ca-root.crt \
/etc/ssl/cert.pem \ /etc/ssl/cert.pem \
"$cac"; do "$cac"; do
if test -f "$a"; then if test -f "$a"; then
ca="$a" ca="$a"
break break
fi fi
done done
fi
if test "x$want_capath" = "xunset" -a "x$ca" = "xno" -a \
"x$OPENSSL_ENABLED" = "x1"; then
for a in /etc/ssl/certs/; do
if test -d "$a" && ls "$a"/[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]].0 >/dev/null 2>/dev/null; then
capath="$a"
break
fi
done
fi
else
dnl no option given and cross-compiling
AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling])
fi fi
if test "x$want_capath" = "xunset" -a "x$ca" = "xno" -a \
"x$OPENSSL_ENABLED" = "x1"; then
for a in /etc/ssl/certs/; do
if test -d "$a" && ls "$a"/[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]].0 >/dev/null 2>/dev/null; then
capath="$a"
break
fi
done
fi
else
dnl no option given and cross-compiling
AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling])
fi fi
if test "x$ca" != "xno"; then if test "x$ca" != "xno"; then

View File

@@ -150,7 +150,6 @@ dnl initialize all the info variables
curl_ssl_msg="no (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )" curl_ssl_msg="no (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )"
curl_ssh_msg="no (--with-libssh2)" curl_ssh_msg="no (--with-libssh2)"
curl_zlib_msg="no (--with-zlib)" curl_zlib_msg="no (--with-zlib)"
curl_krb4_msg="no (--with-krb4*)"
curl_gss_msg="no (--with-gssapi)" curl_gss_msg="no (--with-gssapi)"
curl_spnego_msg="no (--with-spnego)" curl_spnego_msg="no (--with-spnego)"
curl_tls_srp_msg="no (--enable-tls-srp)" curl_tls_srp_msg="no (--enable-tls-srp)"
@@ -1066,6 +1065,7 @@ AC_HELP_STRING([--disable-ipv6],[Disable ipv6 support]),
AC_TRY_RUN([ /* is AF_INET6 available? */ AC_TRY_RUN([ /* is AF_INET6 available? */
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <stdlib.h> /* for exit() */
main() main()
{ {
if (socket(AF_INET6, SOCK_STREAM, 0) < 0) if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
@@ -1134,101 +1134,6 @@ no)
;; ;;
esac esac
dnl **********************************************************************
dnl Check for the presence of Kerberos4 libraries and headers
dnl **********************************************************************
AC_ARG_WITH(krb4-includes,
AC_HELP_STRING([--with-krb4-includes=DIR],
[Specify location of kerberos4 headers]),[
CPPFLAGS="$CPPFLAGS -I$withval"
KRB4INC="$withval"
want_krb4=yes
])
AC_ARG_WITH(krb4-libs,
AC_HELP_STRING([--with-krb4-libs=DIR],[Specify location of kerberos4 libs]),[
LDFLAGS="$LDFLAGS -L$withval"
KRB4LIB="$withval"
want_krb4=yes
])
OPT_KRB4=off
AC_ARG_WITH(krb4,dnl
AC_HELP_STRING([--with-krb4=DIR],[where to look for Kerberos4]),[
OPT_KRB4="$withval"
if test X"$OPT_KRB4" != Xno; then
want_krb4="yes"
if test X"$OPT_KRB4" != Xyes; then
LDFLAGS="$LDFLAGS -L$OPT_KRB4/lib$libsuff"
KRB4LIB="$OPT_KRB4/lib$libsuff"
CPPFLAGS="$CPPFLAGS -I$OPT_KRB4/include"
KRB4INC="$OPT_KRB4/include"
fi
fi
])
AC_MSG_CHECKING([if Kerberos4 support is requested])
if test "$want_krb4" = yes
then
if test "$ipv6" = "yes"; then
echo krb4 is not compatible with IPv6
exit 1
fi
AC_MSG_RESULT(yes)
dnl Check for & handle argument to --with-krb4
AC_MSG_CHECKING(where to look for Kerberos4)
if test X"$OPT_KRB4" = Xyes
then
AC_MSG_RESULT([defaults])
else
AC_MSG_RESULT([libs in $KRB4LIB, headers in $KRB4INC])
fi
dnl Check for DES library
AC_CHECK_LIB(des, des_pcbc_encrypt,
[
AC_CHECK_HEADERS(des.h)
dnl resolv lib?
AC_CHECK_FUNC(res_search, , [AC_CHECK_LIB(resolv, res_search)])
dnl Check for the Kerberos4 library
AC_CHECK_LIB(krb, krb_net_read,
[
dnl Check for header files
AC_CHECK_HEADERS(krb.h)
dnl we found the required libraries, add to LIBS
LIBS="-lkrb -lcom_err -ldes $LIBS"
dnl Check for function krb_get_our_ip_for_realm
dnl this is needed for NAT networks
AC_CHECK_FUNCS(krb_get_our_ip_for_realm)
dnl add define KRB4
AC_DEFINE(HAVE_KRB4, 1,
[if you have the Kerberos4 libraries (including -ldes)])
dnl substitute it too!
KRB4_ENABLED=1
AC_SUBST(KRB4_ENABLED)
curl_krb4_msg="enabled"
dnl the krb4 stuff needs a strlcpy()
AC_CHECK_FUNCS(strlcpy)
])
])
else
AC_MSG_RESULT(no)
fi
dnl ********************************************************************** dnl **********************************************************************
dnl Check for FBopenssl(SPNEGO) libraries dnl Check for FBopenssl(SPNEGO) libraries
dnl ********************************************************************** dnl **********************************************************************
@@ -2079,6 +1984,9 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
if test "x$USE_CYASSL" = "xyes"; then if test "x$USE_CYASSL" = "xyes"; then
AC_MSG_NOTICE([detected CyaSSL]) AC_MSG_NOTICE([detected CyaSSL])
dnl cyassl/ctaocrypt/types.h needs SIZEOF_LONG_LONG defined!
AC_CHECK_SIZEOF(long long)
LIBS="-lcyassl -lm $LIBS" LIBS="-lcyassl -lm $LIBS"
if test -n "$cyassllib"; then if test -n "$cyassllib"; then
@@ -2163,8 +2071,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
CPPFLAGS="$CPPFLAGS $addcflags" CPPFLAGS="$CPPFLAGS $addcflags"
fi fi
dnl The function PK11_CreateGenericObject is needed to load libnsspem.so dnl The function SSL_VersionRangeSet() is needed to enable TLS > 1.0
AC_CHECK_LIB(nss3, PK11_CreateGenericObject, AC_CHECK_LIB(nss3, SSL_VersionRangeSet,
[ [
AC_DEFINE(USE_NSS, 1, [if NSS is enabled]) AC_DEFINE(USE_NSS, 1, [if NSS is enabled])
AC_SUBST(USE_NSS, [1]) AC_SUBST(USE_NSS, [1])
@@ -2180,14 +2088,6 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
if test "x$USE_NSS" = "xyes"; then if test "x$USE_NSS" = "xyes"; then
AC_MSG_NOTICE([detected NSS version $version]) AC_MSG_NOTICE([detected NSS version $version])
dnl NSS_InitContext() was introduced in NSS 3.12.5 and helps to prevent
dnl collisions on NSS initialization/shutdown with other libraries
AC_CHECK_FUNC(NSS_InitContext,
[
AC_DEFINE(HAVE_NSS_INITCONTEXT, 1, [if you have the NSS_InitContext function])
AC_SUBST(HAVE_NSS_INITCONTEXT, [1])
])
dnl when shared libs were found in a path that the run-time dnl when shared libs were found in a path that the run-time
dnl linker doesn't search through, we need to add it to dnl linker doesn't search through, we need to add it to
dnl LD_LIBRARY_PATH to prevent further configure tests to fail dnl LD_LIBRARY_PATH to prevent further configure tests to fail
@@ -2808,6 +2708,92 @@ dnl http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/ \
dnl genprogc/thread_quick_ref.htm dnl genprogc/thread_quick_ref.htm
dnl **********************************************************************
dnl Check for nghttp2
dnl **********************************************************************
AC_MSG_CHECKING([whether to build with nghttp2])
OPT_H2="no"
AC_ARG_WITH(nghttp2,
AC_HELP_STRING([--with-nghttp2=PATH],[Enable nghttp2 usage])
AC_HELP_STRING([--without-nghttp2],[Disable nghttp2 usage]),
[OPT_H2=$withval])
case "$OPT_H2" in
no)
dnl --without-nghttp2 option used
want_idn="no"
AC_MSG_RESULT([no])
;;
default)
dnl configure option not specified
want_h2="no"
want_h2_path="default"
AC_MSG_RESULT([no])
;;
yes)
dnl --with-nghttp2 option used without path
want_h2="yes"
want_h2_path=""
AC_MSG_RESULT([yes])
;;
*)
dnl --with-nghttp2 option used with path
want_h2="yes"
want_h2_path="$withval"
AC_MSG_RESULT([yes ($withval)])
;;
esac
curl_h2_msg="disabled (--with-nghttp2)"
if test X"$OPT_H2" != Xno; then
dnl backup the pre-librtmp variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
h2pcdir=${want_h2_path}/lib/pkgconfig
CURL_CHECK_PKGCONFIG(libnghttp2, $h2pcdir)
if test "$PKGCONFIG" != "no" ; then
LIB_H2=`CURL_EXPORT_PCDIR([$h2pcdir])
$PKGCONFIG --libs-only-l libnghttp2`
AC_MSG_NOTICE([-l is $LIB_H2])
CPP_H2=`CURL_EXPORT_PCDIR([$h2pcdir]) dnl
$PKGCONFIG --cflags-only-I libnghttp2`
AC_MSG_NOTICE([-I is $CPP_H2])
LD_H2=`CURL_EXPORT_PCDIR([$h2pcdir])
$PKGCONFIG --libs-only-L libnghttp2`
AC_MSG_NOTICE([-L is $LD_H2])
else
dnl To avoid link errors, we do not allow --libnghttp2 without
dnl a pkgconfig file
AC_MSG_ERROR([--with-nghttp2 was specified but could not find libnghttp2 pkg-config file.])
fi
LDFLAGS="$LDFLAGS $LD_H2"
CPPFLAGS="$CPPFLAGS $CPP_H2"
LIBS="$LIB_H2 $LIBS"
AC_CHECK_LIB(nghttp2, nghttp2_session_client_new,
[
AC_CHECK_HEADERS(nghttp2/nghttp2.h,
curl_h2_msg="enabled (nghttp2)"
NGHTTP2_ENABLED=1
AC_DEFINE(USE_NGHTTP2, 1, [if nghttp2 is in use])
AC_SUBST(USE_NGHTTP2, [1])
)
],
dnl not found, revert back to clean variables
LDFLAGS=$CLEANLDFLAGS
CPPFLAGS=$CLEANCPPFLAGS
LIBS=$CLEANLIBS
)
fi
dnl ********************************************************************** dnl **********************************************************************
dnl Back to "normal" configuring dnl Back to "normal" configuring
dnl ********************************************************************** dnl **********************************************************************
@@ -3365,9 +3351,6 @@ if test "x$USE_SSLEAY" = "x1"; then
elif test -n "$SSL_ENABLED"; then elif test -n "$SSL_ENABLED"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" SUPPORT_FEATURES="$SUPPORT_FEATURES SSL"
fi fi
if test "@KRB4_ENABLED@" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES KRB4"
fi
if test "x$IPV6_ENABLED" = "x1"; then if test "x$IPV6_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6"
fi fi
@@ -3397,6 +3380,10 @@ if test "x$USE_TLS_SRP" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi fi
if test "x$USE_NGHTTP2" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi
AC_SUBST(SUPPORT_FEATURES) AC_SUBST(SUPPORT_FEATURES)
dnl For supported protocols in pkg-config file dnl For supported protocols in pkg-config file
@@ -3542,7 +3529,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
SSL support: ${curl_ssl_msg} SSL support: ${curl_ssl_msg}
SSH support: ${curl_ssh_msg} SSH support: ${curl_ssh_msg}
zlib support: ${curl_zlib_msg} zlib support: ${curl_zlib_msg}
krb4 support: ${curl_krb4_msg}
GSSAPI support: ${curl_gss_msg} GSSAPI support: ${curl_gss_msg}
SPNEGO support: ${curl_spnego_msg} SPNEGO support: ${curl_spnego_msg}
TLS-SRP support: ${curl_tls_srp_msg} TLS-SRP support: ${curl_tls_srp_msg}
@@ -3561,6 +3547,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
RTSP support: ${curl_rtsp_msg} RTSP support: ${curl_rtsp_msg}
RTMP support: ${curl_rtmp_msg} RTMP support: ${curl_rtmp_msg}
metalink support: ${curl_mtlnk_msg} metalink support: ${curl_mtlnk_msg}
HTTP2 support: ${curl_h2_msg}
Protocols: ${SUPPORT_PROTOCOLS} Protocols: ${SUPPORT_PROTOCOLS}
]) ])

46
contributors.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://curl.haxx.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
###########################################################################
#
# This script shows all mentioned contributors from <hash> until HEAD. To aid
# when writing RELEASE-NOTES and THANKS.
#
start=$1
if test -z "$start"; then
echo "Usage: $0 <since this tag/hash>"
fi
# filter out Author:, Commit: and *by: lines
# cut off the email parts
# cut off spaces first and last on the line
# only count names with a space (ie more than one word)
# sort all unique names
git log $start..HEAD | \
egrep '(Author|Commit|by):' | \
cut -d: -f2- | \
cut '-d<' -f1 | \
sed -e 's/^ //' -e 's/ $//g' | \
grep ' ' | \
sort -u

130
docs/FAQ
View File

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

View File

@@ -43,7 +43,7 @@ Portability
openldap 2.0 openldap 2.0
MIT krb5 lib 1.2.4 MIT krb5 lib 1.2.4
qsossl V5R3M0 qsossl V5R3M0
NSS 3.12.x NSS 3.14.x
axTLS 1.2.7 axTLS 1.2.7
Heimdal ? Heimdal ?

View File

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

View File

@@ -37,7 +37,7 @@ EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \ README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \
KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \ KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
$(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \ $(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \
MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS SECURITY
MAN2HTML= roffit < $< >$@ MAN2HTML= roffit < $< >$@

91
docs/SECURITY Normal file
View File

@@ -0,0 +1,91 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
CURL SECURITY FOR DEVELOPERS
This document is intended to provide guidance to curl developers on how
security vulnerabilities should be handled.
PUBLISHING INFORMATION
All known and public curl or libcurl related vulnerabilities are listed at
http://curl.haxx.se/docs/security.html
Security vulnerabilities should not be entered in the project's public bug
tracker unless the necessary configuration is in place to limit access to the
issue to only the reporter and the project's security team.
VULNERABILITY HANDLING
The typical process for handling a new security vulnerability is as follows.
No information should be made public about a vulnerability until it is
formally announced at the end of this process. That means, for example that a
bug tracker entry must NOT be created to track the issue since that will make
the issue public and it should not be discussed on any of the project's public
mailing lists. Also messages associated with any commits should not make
any reference to the security nature of the commit if done prior to the public
announcement.
- The person discovering the issue, the reporter, reports the vulnerability
privately to curl-security@haxx.se. That's an email alias that reaches a
handful of selected and trusted people.
- Messages that do not relate to the reporting or managing of an undisclosed
security vulnerability in curl or libcurl are ignored and no further action
is required.
- A person in the security team sends an e-mail to the original reporter to
acknowledge the report.
- The security team investigates the report and either rejects it or accepts
it.
- If the report is rejected, the team writes to the reporter to explain why.
- If the report is accepted, the team writes to the reporter to let him/her
know it is accepted and that they are working on a fix.
- The security team discusses the problem, works out a fix, considers the
impact of the problem and suggests a release schedule. This discussion
should involve the reporter as much as possible.
- The release of the information should be "as soon as possible" and is most
often synced with an upcoming release that contains the fix. If the
reporter, or anyone else, thinks the next planned release is too far away
then a separate earlier release for security reasons should be considered.
- Write a security advisory draft about the problem that explains what the
problem is, its impact, which versions it affects, solutions or
work-arounds, when the release is out and make sure to credit all
contributors properly.
- Request a CVE number from distros@openwall.org[1] when also informing and
preparing them for the upcoming public security vulnerability announcement -
attach the advisory draft for information. Note that 'distros' won't accept
an embargo longer than 19 days.
- Update the "security advisory" with the CVE number.
- The security team commits the fix in a private branch. The commit message
should ideally contain the CVE number. This fix is usually also distributed
to the 'distros' mailing list to allow them to use the fix prior to the
public announcement.
- At the day of the next release, the private branch is merged into the master
branch and pushed. Once pushed, the information is accessible to the public
and the actual release should follow suit immediately afterwards.
- The project team creates a release that includes the fix.
- The project team announces the release and the vulnerability to the world in
the same manner we always announce releases. It gets sent to the
curl-announce, curl-library and curl-users mailing lists.
- The security web page on the web site should get the new vulernability
mentioned.
[1] = http://oss-security.openwall.org/wiki/mailing-lists/distros

View File

@@ -27,6 +27,7 @@ Alessandro Vesely
Alex Bligh Alex Bligh
Alex Fishman Alex Fishman
Alex Gruz Alex Gruz
Alex McLellan
Alex Neblett Alex Neblett
Alex Suykov Alex Suykov
Alex Vinnik Alex Vinnik
@@ -62,6 +63,7 @@ Andreas Schuldei
Andreas Wurf Andreas Wurf
Andrei Benea Andrei Benea
Andrei Cipu Andrei Cipu
Andrej E Baranov
Andres Garcia Andres Garcia
Andrew Benham Andrew Benham
Andrew Biggs Andrew Biggs
@@ -109,9 +111,11 @@ Benbuck Nason
Benjamin Gerard Benjamin Gerard
Benjamin Gilbert Benjamin Gilbert
Benjamin Johnson Benjamin Johnson
Benoit Sigoure
Bernard Leak Bernard Leak
Bernhard Reutner-Fischer Bernhard Reutner-Fischer
Bertrand Demiddelaer Bertrand Demiddelaer
Bill Doyle
Bill Egert Bill Egert
Bill Hoffman Bill Hoffman
Bill Middlecamp Bill Middlecamp
@@ -154,6 +158,7 @@ Charles Kerr
Chih-Chung Chang Chih-Chung Chang
Chris "Bob Bob" Chris "Bob Bob"
Chris Combes Chris Combes
Chris Conlon
Chris Conroy Chris Conroy
Chris Deidun Chris Deidun
Chris Flerackers Chris Flerackers
@@ -181,6 +186,7 @@ Clarence Gardner
Clemens Gruber Clemens Gruber
Clifford Wolf Clifford Wolf
Cody Jones Cody Jones
Colby Ranger
Colin Hogben Colin Hogben
Colin Watson Colin Watson
Colm Buckley Colm Buckley
@@ -194,6 +200,7 @@ Cristian Rodríguez
Curt Bogmine Curt Bogmine
Cyrill Osterwalder Cyrill Osterwalder
Cédric Deltheil Cédric Deltheil
D. Flinkmann
Dag Ekengren Dag Ekengren
Dagobert Michelsen Dagobert Michelsen
Damien Adant Damien Adant
@@ -221,6 +228,7 @@ Dave Halbakken
Dave Hamilton Dave Hamilton
Dave May Dave May
Dave Reisner Dave Reisner
Dave Thompson
Dave Vasilevsky Dave Vasilevsky
David Bau David Bau
David Binderman David Binderman
@@ -244,13 +252,16 @@ David Shaw
David Strauss David Strauss
David Tarendash David Tarendash
David Thiel David Thiel
David Walser
David Wright David Wright
David Yan David Yan
Dengminwen Dengminwen
Derek Higgins
Detlef Schmier Detlef Schmier
Didier Brisebourg Didier Brisebourg
Diego Casorran Diego Casorran
Dima Barsky Dima Barsky
Dima Tisnek
Dimitre Dimitrov Dimitre Dimitrov
Dimitris Sarris Dimitris Sarris
Dinar Dinar
@@ -289,6 +300,7 @@ Eelco Dolstra
Eetu Ojanen Eetu Ojanen
Eldar Zaitov Eldar Zaitov
Ellis Pritchard Ellis Pritchard
Elmira A Semenova
Emanuele Bovisio Emanuele Bovisio
Emil Romanus Emil Romanus
Emiliano Ida Emiliano Ida
@@ -298,6 +310,7 @@ Eric Cooper
Eric Hu Eric Hu
Eric Landes Eric Landes
Eric Lavigne Eric Lavigne
Eric Lubin
Eric Melville Eric Melville
Eric Mertens Eric Mertens
Eric Rautman Eric Rautman
@@ -318,10 +331,12 @@ Fabian Hiernaux
Fabian Keil Fabian Keil
Fabrizio Ammollo Fabrizio Ammollo
Fedor Karpelevitch Fedor Karpelevitch
Felix Yan
Felix von Leitner Felix von Leitner
Feng Tu Feng Tu
Florian Schoppmann Florian Schoppmann
Forrest Cahoon Forrest Cahoon
Francois Charlier
Frank Hempel Frank Hempel
Frank Keeney Frank Keeney
Frank McGeough Frank McGeough
@@ -342,11 +357,13 @@ Gautam Kachroo
Gautam Mani Gautam Mani
Gavrie Philipson Gavrie Philipson
Gaz Iqbal Gaz Iqbal
Geoff Beier
Georg Horn Georg Horn
Georg Huettenegger Georg Huettenegger
Georg Lippitsch Georg Lippitsch
Georg Wicherski Georg Wicherski
Gerd v. Egidy Gerd v. Egidy
Gergely Nagy
Gerhard Herre Gerhard Herre
Gerrit Bruchhäuser Gerrit Bruchhäuser
Ghennadi Procopciuc Ghennadi Procopciuc
@@ -362,6 +379,8 @@ Giuseppe D'Ambrosio
Glen Nakamura Glen Nakamura
Glen Scott Glen Scott
Gokhan Sengun Gokhan Sengun
Gordon Marler
Gorilla Maguila
Grant Erickson Grant Erickson
Greg Hewgill Greg Hewgill
Greg Morse Greg Morse
@@ -384,8 +403,10 @@ Hans-Jurgen May
Hardeep Singh Hardeep Singh
Harshal Pradhan Harshal Pradhan
Hauke Duden Hauke Duden
He Qin
Heikki Korpela Heikki Korpela
Heinrich Ko Heinrich Ko
Heinrich Schaefer
Hendrik Visage Hendrik Visage
Henrik Storner Henrik Storner
Henry Ludemann Henry Ludemann
@@ -422,6 +443,7 @@ James Bursa
James Cheng James Cheng
James Clancy James Clancy
James Cone James Cone
James Dury
James Gallagher James Gallagher
James Griffiths James Griffiths
James Housley James Housley
@@ -441,6 +463,7 @@ Jason Glasgow
Jason Liu Jason Liu
Jason McDonald Jason McDonald
Jason S. Priebe Jason S. Priebe
Javier Barroso
Jay Austin Jay Austin
Jayesh A Shah Jayesh A Shah
Jaz Fresh Jaz Fresh
@@ -453,6 +476,7 @@ Jean-Noel Rouvignac
Jean-Philippe Barrette-LaPierre Jean-Philippe Barrette-LaPierre
Jeff Connelly Jeff Connelly
Jeff Johnson Jeff Johnson
Jeff King
Jeff Lawson Jeff Lawson
Jeff Phillips Jeff Phillips
Jeff Pohlmeyer Jeff Pohlmeyer
@@ -462,6 +486,7 @@ Jeremy Friesner
Jeremy Huddleston Jeremy Huddleston
Jerome Muffat-Meridol Jerome Muffat-Meridol
Jerome Vouillon Jerome Vouillon
Jerry Krinock
Jerry Wu Jerry Wu
Jes Badwal Jes Badwal
Jesper Jensen Jesper Jensen
@@ -486,6 +511,7 @@ Johannes Bauer
John Bradshaw John Bradshaw
John Crow John Crow
John Dennis John Dennis
John Dunn
John E. Malmberg John E. Malmberg
John Gardiner Myers John Gardiner Myers
John Janssen John Janssen
@@ -569,6 +595,7 @@ Krishnendu Majumdar
Krister Johansen Krister Johansen
Kristian Gunstone Kristian Gunstone
Kristian Köhntopp Kristian Köhntopp
Kyle L. Huff
Kyle Sallee Kyle Sallee
Lachlan O'Dea Lachlan O'Dea
Larry Campbell Larry Campbell
@@ -611,6 +638,7 @@ Mandy Wu
Manfred Schwarb Manfred Schwarb
Manuel Massing Manuel Massing
Marc Boucher Marc Boucher
Marc Deslauriers
Marc Doughty Marc Doughty
Marc Hoersken Marc Hoersken
Marc Kleine-Budde Marc Kleine-Budde
@@ -618,6 +646,7 @@ Marcel Raad
Marcel Roelofs Marcel Roelofs
Marcelo Juchem Marcelo Juchem
Marcin Adamski Marcin Adamski
Marcin Gryszkalis
Marcin Konicki Marcin Konicki
Marco G. Salvagno Marco G. Salvagno
Marco Maggi Marco Maggi
@@ -672,6 +701,7 @@ Maxim Prohorov
Maxime Larocque Maxime Larocque
Mehmet Bozkurt Mehmet Bozkurt
Mekonikum Mekonikum
Melissa Mears
Mettgut Jamalla Mettgut Jamalla
Michael Benedict Michael Benedict
Michael Calmer Michael Calmer
@@ -683,6 +713,7 @@ Michael Jahn
Michael Jerris Michael Jerris
Michael Mealling Michael Mealling
Michael Mueller Michael Mueller
Michael Osipov
Michael Smith Michael Smith
Michael Stillwell Michael Stillwell
Michael Wallner Michael Wallner
@@ -700,6 +731,7 @@ Mike Crowe
Mike Dobbs Mike Dobbs
Mike Giancola Mike Giancola
Mike Hommey Mike Hommey
Mike Mio
Mike Power Mike Power
Mike Protts Mike Protts
Mike Revi Mike Revi
@@ -744,6 +776,7 @@ Olaf Flebbe
Olaf Stueben Olaf Stueben
Olaf Stüben Olaf Stüben
Oliver Gondža Oliver Gondža
Oliver Kuckertz
Olivier Berger Olivier Berger
Oren Tirosh Oren Tirosh
Ori Avtalion Ori Avtalion
@@ -762,8 +795,10 @@ Patrick Scott
Patrick Smith Patrick Smith
Patrik Thunstrom Patrik Thunstrom
Pau Garcia i Quiles Pau Garcia i Quiles
Paul Donohue
Paul Harrington Paul Harrington
Paul Howarth Paul Howarth
Paul Marks
Paul Marquis Paul Marquis
Paul Moore Paul Moore
Paul Nolan Paul Nolan
@@ -792,6 +827,8 @@ Peter Todd
Peter Verhas Peter Verhas
Peter Wullinger Peter Wullinger
Peteris Krumins Peteris Krumins
Petr Bahula
Petr Pisar
Phil Blundell Phil Blundell
Phil Karn Phil Karn
Phil Lisiecki Phil Lisiecki
@@ -875,6 +912,7 @@ Roland Zimmermann
Rolland Dudemaine Rolland Dudemaine
Roman Koifman Roman Koifman
Roman Mamedov Roman Mamedov
Romulo A. Ceccon
Ron Zapp Ron Zapp
Rosimildo da Silva Rosimildo da Silva
Roy Shan Roy Shan
@@ -884,6 +922,7 @@ Rutger Hofman
Ryan Chan Ryan Chan
Ryan Nelson Ryan Nelson
Ryan Schmidt Ryan Schmidt
Rémy Léone
S. Moonesamy S. Moonesamy
Salvador Dávila Salvador Dávila
Salvatore Sorrentino Salvatore Sorrentino
@@ -909,11 +948,13 @@ Sebastian Rasmussen
Sebastien Willemijns Sebastien Willemijns
Senthil Raja Velu Senthil Raja Velu
Sergei Nikulov Sergei Nikulov
Sergey Tatarincev
Sergio Ballestrero Sergio Ballestrero
Seshubabu Pasam Seshubabu Pasam
Sh Diao Sh Diao
Sharad Gupta Sharad Gupta
Shard Shard
Shawn Landden
Shawn Poulson Shawn Poulson
Shmulik Regev Shmulik Regev
Siddhartha Prakash Jain Siddhartha Prakash Jain
@@ -997,6 +1038,7 @@ Tom Mueller
Tom Regner Tom Regner
Tom Wright Tom Wright
Tom Zerucha Tom Zerucha
Tomas Hoger
Tomas Mlcoch Tomas Mlcoch
Tomas Pospisek Tomas Pospisek
Tomas Szepe Tomas Szepe
@@ -1014,7 +1056,9 @@ Traian Nicolescu
Troels Walsted Hansen Troels Walsted Hansen
Troy Engel Troy Engel
Tupone Alfredo Tupone Alfredo
Tyler Hall
Ulf Härnhammar Ulf Härnhammar
Ulf Samuelsson
Ulrich Doehner Ulrich Doehner
Ulrich Zadow Ulrich Zadow
Venkat Akella Venkat Akella
@@ -1041,15 +1085,18 @@ Wesley Laxton
Wesley Miaw Wesley Miaw
Wez Furlong Wez Furlong
Wilfredo Sanchez Wilfredo Sanchez
Will Dietz
Willem Sparreboom Willem Sparreboom
Wojciech Zwiefka Wojciech Zwiefka
Wouter Van Rooy Wouter Van Rooy
Wu Yongzheng Wu Yongzheng
Xavier Bouchoux Xavier Bouchoux
Yaakov Selkowitz
Yamada Yasuharu Yamada Yasuharu
Yang Tse Yang Tse
Yarram Sunil Yarram Sunil
Yehoshua Hershberg Yehoshua Hershberg
Yi Huang
Yukihiro Kawada Yukihiro Kawada
Yuriy Sosov Yuriy Sosov
Yves Arrouye Yves Arrouye

View File

@@ -16,8 +16,7 @@
1.3 struct lifreq 1.3 struct lifreq
1.4 signal-based resolver timeouts 1.4 signal-based resolver timeouts
1.5 get rid of PATH_MAX 1.5 get rid of PATH_MAX
1.6 Happy Eyeball dual stack connect 1.6 Modified buffer size approach
1.7 Modified buffer size approach
2. libcurl - multi interface 2. libcurl - multi interface
2.1 More non-blocking 2.1 More non-blocking
@@ -39,6 +38,7 @@
5.2 support FF3 sqlite cookie files 5.2 support FF3 sqlite cookie files
5.3 Rearrange request header order 5.3 Rearrange request header order
5.4 HTTP2/SPDY 5.4 HTTP2/SPDY
5.5 auth= in URLs
6. TELNET 6. TELNET
6.1 ditch stdin 6.1 ditch stdin
@@ -48,17 +48,14 @@
7. SMTP 7. SMTP
7.1 Pipelining 7.1 Pipelining
7.2 Graceful base64 decoding failure 7.2 Enhanced capability support
7.3 Enhanced capability support
8. POP3 8. POP3
8.1 Pipelining 8.1 Pipelining
8.2 Graceful base64 decoding failure 8.2 Enhanced capability support
8.3 Enhanced capability support
9. IMAP 9. IMAP
9.1 Graceful base64 decoding failure 9.1 Enhanced capability support
9.2 Enhanced capability support
10. LDAP 10. LDAP
10.1 SASL based authentication mechanisms 10.1 SASL based authentication mechanisms
@@ -157,19 +154,7 @@
we need libssh2 to properly tell us when we pass in a too small buffer and we need libssh2 to properly tell us when we pass in a too small buffer and
its current API (as of libssh2 1.2.7) doesn't. its current API (as of libssh2 1.2.7) doesn't.
1.6 Happy Eyeball dual stack connect 1.6 Modified buffer size approach
In order to make alternative technologies not suffer when transitioning, like
when introducing IPv6 as an alternative to IPv4 and there are more than one
option existing simultaneously there are reasons to reconsider internal
choices.
To make libcurl do blazing fast IPv6 in a dual-stack configuration, this needs
to be addressed:
http://tools.ietf.org/html/rfc6555
1.7 Modified buffer size approach
Current libcurl allocates a fixed 16K size buffer for download and an Current libcurl allocates a fixed 16K size buffer for download and an
additional 16K for upload. They are always unconditionally part of the easy additional 16K for upload. They are always unconditionally part of the easy
@@ -300,6 +285,17 @@
be a better option, either used directly or wrapped with a more spindly-like be a better option, either used directly or wrapped with a more spindly-like
API. API.
5.5 auth= in URLs
Add the ability to specify the preferred authentication mechanism to use by
using ;auth=<mech> in the login part of the URL.
For example:
http://test:pass;auth=NTLM@example.com would be equivalent to specifing --user
test:pass;auth=NTLM or --user test:pass --ntlm from the command line.
Additionally this should be implemented for proxy base URLs as well.
6. TELNET 6. TELNET
@@ -331,14 +327,7 @@ to provide the data to send.
Add support for pipelining emails. Add support for pipelining emails.
7.2 Graceful base64 decoding failure 7.2 Enhanced capability support
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 Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the EHLO command. capabilities returned from the EHLO command.
@@ -349,28 +338,14 @@ to provide the data to send.
Add support for pipelining commands. Add support for pipelining commands.
8.2 Graceful base64 decoding failure 8.2 Enhanced capability support
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 Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the CAPA command. capabilities returned from the CAPA command.
9. IMAP 9. IMAP
9.1 Graceful base64 decoding failure 9.1 Enhanced capability support
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 Add the ability, for an application that uses libcurl, to obtain the list of
capabilities returned from the CAPABILITY command. capabilities returned from the CAPABILITY command.

View File

@@ -103,6 +103,18 @@ any response data to the terminal.
If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your If you prefer a progress "bar" instead of the regular meter, \fI-#\fP is your
friend. friend.
.SH OPTIONS .SH OPTIONS
Options start with one or two dashes. Many of the options require an addition
value next to it.
The short "single-dash" form of the options, -d for example, may be used with
or without a space between it and its value, although a space is a recommended
separator. The long "double-dash" form, --data for example, requires a space
between it and its value.
Short version options that don't need any additional values can be used
immediately next to each other, like for example you can specify all the
options -O, -L and -v at once as -OLv.
In general, all boolean options are enabled with --\fBoption\fP and yet again In general, all boolean options are enabled with --\fBoption\fP and yet again
disabled with --\fBno-\fPoption. That is, you use the exact same option name disabled with --\fBno-\fPoption. That is, you use the exact same option name
but prefix it with "no-". However, in this list we mostly only list and show but prefix it with "no-". However, in this list we mostly only list and show
@@ -113,8 +125,14 @@ same command line option.)
Make curl display progress as a simple progress bar instead of the standard, Make curl display progress as a simple progress bar instead of the standard,
more informational, meter. more informational, meter.
.IP "-0, --http1.0" .IP "-0, --http1.0"
(HTTP) Forces curl to issue its requests using HTTP 1.0 instead of using its (HTTP) Tells curl to use HTTP version 1.0 instead of using its internally
internally preferred: HTTP 1.1. preferred: HTTP 1.1.
.IP "--http1.1"
(HTTP) Tells curl to use HTTP version 1.1. This is the internal default
version. (Added in 7.33.0)
.IP "--http2.0"
(HTTP) Tells curl to issue its requests using HTTP 2.0. This requires that the
underlying libcurl was built to support it. (Added in 7.33.0)
.IP "-1, --tlsv1" .IP "-1, --tlsv1"
(SSL) (SSL)
Forces curl to use TLS version 1 when negotiating with a remote TLS server. Forces curl to use TLS version 1 when negotiating with a remote TLS server.
@@ -272,7 +290,8 @@ If you start the data with the letter @, the rest should be a file name to
read the data from, or - if you want curl to read the data from stdin. The read the data from, or - if you want curl to read the data from stdin. The
contents of the file must already be URL-encoded. Multiple files can also be contents of the file must already be URL-encoded. Multiple files can also be
specified. Posting data from a file named 'foobar' would thus be done with specified. Posting data from a file named 'foobar' would thus be done with
\fI--data @foobar\fP. \fI--data\fP @foobar. When --data is told to read from a file like that,
carriage returns and newlines will be stripped out.
.IP "-D, --dump-header <file>" .IP "-D, --dump-header <file>"
Write the protocol headers to the specified file. Write the protocol headers to the specified file.
@@ -294,7 +313,7 @@ whatsoever.
If you start the data with the letter @, the rest should be a filename. Data If you start the data with the letter @, the rest should be a filename. Data
is posted in a similar manner as \fI--data-ascii\fP does, except that newlines is posted in a similar manner as \fI--data-ascii\fP does, except that newlines
are preserved and conversions are never done. and carriage returns are preserved and conversions are never done.
If this option is used several times, the ones following the first will append If this option is used several times, the ones following the first will append
data as described in \fI-d, --data\fP. data as described in \fI-d, --data\fP.
@@ -369,6 +388,39 @@ is an alias for \fB--disable-epsv\fP.
Disabling EPSV only changes the passive behavior. If you want to switch to Disabling EPSV only changes the passive behavior. If you want to switch to
active mode you need to use \fI-P, --ftp-port\fP. active mode you need to use \fI-P, --ftp-port\fP.
.IP "--dns-interface <interface>"
Tell curl to send outgoing DNS requests through <interface>. This option
is a counterpart to \fI--interface\fP (which does not affect DNS). The
supplied string must be an interface name (not an address).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "--dns-ipv4-addr <ip-address>"
Tell curl to bind to <ip-address> when making IPv4 DNS requests, so that
the DNS requests originate from this address. The argument should be a
single IPv4 address.
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "--dns-ipv6-addr <ip-address>"
Tell curl to bind to <ip-address> when making IPv6 DNS requests, so that
the DNS requests originate from this address. The argument should be a
single IPv6 address.
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "--dns-servers <ip-address,ip-address>"
Set the list of DNS servers to be used instead of the system default.
The list of IP addresses should be separated with commas. Port numbers
may also optionally be given as \fI:<port-number>\fP after each IP
address.
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. (Added in
7.33.0)
.IP "-e, --referer <URL>" .IP "-e, --referer <URL>"
(HTTP) Sends the "Referer Page" information to the HTTP server. This can also (HTTP) Sends the "Referer Page" information to the HTTP server. This can also
be set with the \fI-H, --header\fP flag of course. When used with be set with the \fI-H, --header\fP flag of course. When used with
@@ -380,7 +432,8 @@ If this option is used several times, the last one will be used.
.IP "-E, --cert <certificate[:password]>" .IP "-E, --cert <certificate[:password]>"
(SSL) Tells curl to use the specified client certificate file when getting a (SSL) Tells curl to use the specified client certificate file when getting a
file with HTTPS, FTPS or another SSL-based protocol. The certificate must be file with HTTPS, FTPS or another SSL-based protocol. The certificate must be
in PEM format. If the optional password isn't specified, it will be queried in PKCS#12 format if using Secure Transport, or PEM format if using any other
engine. If the optional password isn't specified, it will be queried
for on the terminal. Note that this option assumes a \&"certificate" file that for on the terminal. Note that this option assumes a \&"certificate" file that
is the private key and the private certificate concatenated! See \fI--cert\fP is the private key and the private certificate concatenated! See \fI--cert\fP
and \fI--key\fP to specify them independently. and \fI--key\fP to specify them independently.
@@ -396,9 +449,10 @@ recognized as password delimiter. If the nickname contains "\\", it needs to
be escaped as "\\\\" so that it is not recognized as an escape character. 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 (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 certificate string can either be the name of a certificate/private key in the
user keychain. The private key corresponding to the certificate, and system or user keychain, or the path to a PKCS#12-encoded certificate and
certificate chain (if any), must also be present in the keychain. private key. If you want to use a file from the current directory, please
precede it with "./" prefix, in order to avoid confusion with a nickname.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "--engine <name>" .IP "--engine <name>"
@@ -592,10 +646,10 @@ you can specify URLs that contain the letters {}[] without having them being
interpreted by curl itself. Note that these letters are not normal legal URL interpreted by curl itself. Note that these letters are not normal legal URL
contents but they should be encoded according to the URI standard. contents but they should be encoded according to the URI standard.
.IP "-G, --get" .IP "-G, --get"
When used, this option will make all data specified with \fI-d, --data\fP or When used, this option will make all data specified with \fI-d, --data\fP,
\fI--data-binary\fP to be used in an HTTP GET request instead of the POST \fI--data-binary\fP or \fI--data-urlencode\fP to be used in an HTTP GET
request that otherwise would be used. The data will be appended to the URL request instead of the POST request that otherwise would be used. The data
with a '?' separator. will be appended to the URL with a '?' separator.
If used in combination with -I, the POST data will instead be appended to the If used in combination with -I, the POST data will instead be appended to the
URL with a HEAD request. URL with a HEAD request.
@@ -657,6 +711,9 @@ cookies when they're closed down.
(HTTP) This option tells the \fI-O, --remote-name\fP option to use the (HTTP) This option tells the \fI-O, --remote-name\fP option to use the
server-specified Content-Disposition filename instead of extracting a filename server-specified Content-Disposition filename instead of extracting a filename
from the URL. from the URL.
There's no attempt to decode %-sequences (yet) in the provided file name, so
this option may provide you with rather unexpected file names.
.IP "-k, --insecure" .IP "-k, --insecure"
(SSL) This option explicitly allows curl to perform "insecure" SSL connections (SSL) This option explicitly allows curl to perform "insecure" SSL connections
and transfers. All SSL connections are attempted to be made secure by using and transfers. All SSL connections are attempted to be made secure by using
@@ -668,16 +725,21 @@ See this online resource for further details:
.IP "-K, --config <config file>" .IP "-K, --config <config file>"
Specify which config file to read curl arguments from. The config file is a Specify which config file to read curl arguments from. The config file is a
text file in which command line arguments can be written which then will be text file in which command line arguments can be written which then will be
used as if they were written on the actual command line. Options and their used as if they were written on the actual command line.
parameters must be specified on the same config file line, separated by
whitespace, colon, the equals sign or any combination thereof (however, Options and their parameters must be specified on the same config file line,
the preferred separator is the equals sign). If the parameter is to contain separated by whitespace, colon, or the equals sign. Long option names can
whitespace, the parameter must be enclosed within quotes. Within double optionally be given in the config file without the initial double dashes and
quotes, the following escape sequences are available: \\\\, \\", \\t, \\n, if so, the colon or equals characters can be used as separators. If the option
\\r and \\v. A backslash preceding any other letter is ignored. If the is specified with one or two dashes, there can be no colon or equals character
first column of a config line is a '#' character, the rest of the line will be between the option and its parameter.
treated as a comment. Only write one option per physical line in the config
file. If the parameter is to contain whitespace, the parameter must be enclosed
within quotes. Within double quotes, the following escape sequences are
available: \\\\, \\", \\t, \\n, \\r and \\v. A backslash preceding any other
letter is ignored. If the first column of a config line is a '#' character,
the rest of the line will be treated as a comment. Only write one option per
physical line in the config file.
Specify the filename to -K, --config as '-' to make curl read the file from Specify the filename to -K, --config as '-' to make curl read the file from
stdin. stdin.
@@ -688,9 +750,6 @@ line. So, it could look similar to this:
url = "http://curl.haxx.se/docs/" url = "http://curl.haxx.se/docs/"
Long option names can optionally be given in the config file without the
initial double dashes.
When curl is invoked, it always (unless \fI-q\fP is used) checks for a default When curl is invoked, it always (unless \fI-q\fP is used) checks for a default
config file and uses it if found. The default config file is checked for in config file and uses it if found. The default config file is checked for in
the following places in this order: the following places in this order:
@@ -752,15 +811,23 @@ see if your curl supports it.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-l, --list-only" .IP "-l, --list-only"
(FTP) (FTP)
When listing an FTP directory, this switch forces a name-only view. When listing an FTP directory, this switch forces a name-only view. This is
Especially useful if you want to machine-parse the contents of an FTP especially useful if the user wants to machine-parse the contents of an FTP
directory since the normal directory view doesn't use a standard look directory since the normal directory view doesn't use a standard look or
or format. format. When used like this, the option causes a NLST command to be sent to
the server instead of LIST.
This option causes an FTP NLST command to be sent. Some FTP servers Note: Some FTP servers list only files in their response to NLST; they do not
list only files in their response to NLST; they do not include include sub-directories and symbolic links.
subdirectories and symbolic links.
(POP3)
When retrieving a specific email from POP3, this switch forces a LIST command
to be performed instead of RETR. This is particularly useful if the user wants
to see if a specific message id exists on the server and what size it is.
Note: When combined with \fI-X, --request <command>\fP, this option can be used
to send an UIDL command instead, so the user may use the email's unique
identifier rather than it's message id to make the request. (Added in 7.21.5)
.IP "-L, --location" .IP "-L, --location"
(HTTP/HTTPS) If the server reports that the requested page has moved to a (HTTP/HTTPS) If the server reports that the requested page has moved to a
different location (indicated with a Location: header and a 3XX response code), different location (indicated with a Location: header and a 3XX response code),
@@ -840,10 +907,18 @@ return with exit code 63.
files this option has no effect even if the file transfer ends up being larger files this option has no effect even if the file transfer ends up being larger
than this given limit. This concerns both FTP and HTTP transfers. than this given limit. This concerns both FTP and HTTP transfers.
.IP "--mail-rcpt <address>" .IP "--mail-rcpt <address>"
(SMTP) Specify a single address that the given mail should get sent to. This (SMTP) Specify a single address, user name or mailing list name.
option can be used multiple times to specify many recipients.
(Added in 7.20.0) When performing a mail transfer, the recipient should specify a valid email
address to send the mail to. (Added in 7.20.0)
When performing an address verification (VRFY command), the recipient should be
specified as the user name or user name and domain (as per Section 3.5 of
RFC5321). (Added in 7.34.0)
When performing a mailing list expand (EXPN command), the recipient should be
specified using the mailing list name, such as "Friends" or "London-Office".
(Added in 7.34.0)
.IP "--max-redirs <num>" .IP "--max-redirs <num>"
Set maximum number of redirection-followings allowed. If \fI-L, --location\fP Set maximum number of redirection-followings allowed. If \fI-L, --location\fP
is used, this option can be used to prevent curl from following redirections is used, this option can be used to prevent curl from following redirections
@@ -999,7 +1074,19 @@ Consequentially, the file will be saved in the current working directory. If
you want the file saved in a different directory, make sure you change current you want the file saved in a different directory, make sure you change current
working directory before you invoke curl with the \fB-O, --remote-name\fP flag! working directory before you invoke curl with the \fB-O, --remote-name\fP flag!
There is no URL decoding done on the file name. If it has %20 or other URL
encoded parts of the name, they will end up as-is as file name.
You may use this option as many times as the number of URLs you have. You may use this option as many times as the number of URLs you have.
.IP "--oauth2-bearer"
(IMAP, POP3, SMTP)
Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
is used in conjunction with the user name which can be specified as part of the
\fI--url\fP or \fI-u, --user\fP options.
The Bearer Token and user name are formatted according to RFC 6750.
If this option is used several times, the last one will be used.
.IP "-p, --proxytunnel" .IP "-p, --proxytunnel"
When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP When an HTTP proxy is used (\fI-x, --proxy\fP), this option will cause non-HTTP
protocols to attempt to tunnel through the proxy instead of merely using it to protocols to attempt to tunnel through the proxy instead of merely using it to
@@ -1436,14 +1523,26 @@ Set TLS authentication type. Currently, the only supported option is "SRP",
for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are
specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP". specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP".
(Added in 7.21.4) (Added in 7.21.4)
.IP "--tlsuser <user>"
Set username for use with the TLS authentication method specified with
\fI--tlsauthtype\fP. Requires that \fI--tlspassword\fP also be set. (Added in
7.21.4)
.IP "--tlspassword <password>" .IP "--tlspassword <password>"
Set password for use with the TLS authentication method specified with Set password for use with the TLS authentication method specified with
\fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set. (Added in \fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set. (Added in
7.21.4) 7.21.4)
.IP "--tlsuser <user>"
Set username for use with the TLS authentication method specified with
\fI--tlsauthtype\fP. Requires that \fI--tlspassword\fP also be set. (Added in
7.21.4)
.IP "--tlsv1.0"
(SSL)
Forces curl to use TLS version 1.0 when negotiating with a remote TLS server.
(Added in 7.34.0)
.IP "--tlsv1.1"
(SSL)
Forces curl to use TLS version 1.1 when negotiating with a remote TLS server.
(Added in 7.34.0)
.IP "--tlsv1.2"
(SSL)
Forces curl to use TLS version 1.2 when negotiating with a remote TLS server.
(Added in 7.34.0)
.IP "--tr-encoding" .IP "--tr-encoding"
(HTTP) Request a compressed Transfer-Encoding response using one of the (HTTP) Request a compressed Transfer-Encoding response using one of the
algorithms curl supports, and uncompress the data while receiving it. algorithms curl supports, and uncompress the data while receiving it.
@@ -1473,16 +1572,23 @@ If this option is used several times, the last one will be used.
.IP "--trace-time" .IP "--trace-time"
Prepends a time stamp to each trace or verbose line that curl displays. Prepends a time stamp to each trace or verbose line that curl displays.
(Added in 7.14.0) (Added in 7.14.0)
.IP "-u, --user <user:password>" .IP "-u, --user <user:password;options>"
Specify the user name and password to use for server authentication. Overrides Specify the user name, password and optional login options to use for server
\fI-n, --netrc\fP and \fI--netrc-optional\fP. authentication. Overrides \fI-n, --netrc\fP and \fI--netrc-optional\fP.
If you just give the user name (without entering a colon) curl will prompt for If you simply specify the user name, with or without the login options, curl
a password. will prompt for a password.
If you use an SSPI-enabled curl binary and do NTLM authentication, you can If you use an SSPI-enabled curl binary and perform NTLM authentication, you
force curl to pick up the user name and password from your environment by can force curl to select the user name and password from your environment by
simply specifying a single colon with this option: "-u :". simply specifying a single colon with this option: "-u :" or by specfying the
login options on their own, for example "-u ;auth=NTLM".
You can use the optional login options part to specify protocol specific
options that may be used during authentication. At present only IMAP, POP3 and
SMTP support login options as part of the user login information. For more
information about the login options please see RFC 2384, RFC 5092 and IETF
draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-U, --proxy-user <user:password>" .IP "-U, --proxy-user <user:password>"
@@ -1643,8 +1749,16 @@ to follow location: headers.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>" .IP "-x, --proxy <[protocol://][user:password@]proxyhost[:port]>"
Use the specified HTTP proxy. If the port number is not specified, it is Use the specified proxy.
assumed at port 1080.
The proxy string can be specified with a protocol:// prefix to specify
alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
socks5h:// to request the specific SOCKS version to be used. No protocol
specified, http:// and all others will be treated as HTTP proxies. (The
protocol support was added in curl 7.21.7)
If the port number is not specified in the proxy string, it is assumed to be
1080.
This option overrides existing environment variables that set the proxy to This option overrides existing environment variables that set the proxy to
use. If there's an environment variable setting a proxy, you can set proxy to use. If there's an environment variable setting a proxy, you can set proxy to
@@ -1663,11 +1777,6 @@ The proxy host can be specified the exact same way as the proxy environment
variables, including the protocol prefix (http://) and the embedded user + variables, including the protocol prefix (http://) and the embedded user +
password. password.
From 7.21.7, the proxy string may be specified with a protocol:// prefix to
specify alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
socks5h:// to request the specific SOCKS version to be used. No protocol
specified, http:// and all others will be treated as HTTP proxies.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-X, --request <command>" .IP "-X, --request <command>"
(HTTP) Specifies a custom request method to use when communicating with the (HTTP) Specifies a custom request method to use when communicating with the
@@ -1689,8 +1798,17 @@ option.
Specifies a custom FTP command to use instead of LIST when doing file lists Specifies a custom FTP command to use instead of LIST when doing file lists
with FTP. with FTP.
If this option is used several times, the last one will be used. (POP3)
Specifies a custom POP3 command to use instead of LIST or RETR. (Added in
7.26.0)
(IMAP)
Specifies a custom IMAP command to use insead of LIST. (Added in 7.30.0)
(SMTP)
Specifies a custom SMTP command to use instead of HELP or VRFY. (Added in 7.34.0)
If this option is used several times, the last one will be used.
.IP "--xattr" .IP "--xattr"
When saving output to a file, this option tells curl to store certain file When saving output to a file, this option tells curl to store certain file
metadata in extended file attributes. Currently, the URL is stored in the metadata in extended file attributes. Currently, the URL is stored in the
@@ -1983,6 +2101,8 @@ RTSP: mismatch of Session Identifiers
unable to parse FTP file list unable to parse FTP file list
.IP 88 .IP 88
FTP chunk callback reported error FTP chunk callback reported error
.IP 89
No connection available, the session will be queued
.IP XX .IP XX
More error codes will appear here in future releases. The existing ones More error codes will appear here in future releases. The existing ones
are meant to never change. are meant to never change.

View File

@@ -5,7 +5,7 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
persistant post-callback postit2 sepheaders simple simplepost simplessl \ persistant post-callback postit2 sepheaders simple simplepost simplessl \
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \ sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \ smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \
progressfunc pop3s pop3slist imap url2file sftpget ftpsget progressfunc pop3s pop3slist imap url2file sftpget ftpsget postinmemory
# These examples require external dependencies that may not be commonly # These examples require external dependencies that may not be commonly
# available on POSIX systems, so don't bother attempting to compile them here. # available on POSIX systems, so don't bother attempting to compile them here.
@@ -13,4 +13,4 @@ COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c \
ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \ ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \ opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \ smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
multi-uv.c xmlstream.c usercertinmem.c multi-uv.c xmlstream.c usercertinmem.c sessioninfo.c

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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -98,10 +98,6 @@ int main(void)
* bytes big and contains the remote file. * bytes big and contains the remote file.
* *
* Do something nice with it! * Do something nice with it!
*
* You should be aware of the fact that at this point we might have an
* allocated data block, and nothing has yet deallocated that data. So when
* you're done with it, you should free() it as a nice application.
*/ */
printf("%lu bytes retrieved\n", (long)chunk.size); printf("%lu bytes retrieved\n", (long)chunk.size);

View File

@@ -22,8 +22,6 @@
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h>
#include <curl/curl.h> #include <curl/curl.h>
/* /*
@@ -59,7 +57,6 @@ int main(int argc, char **argv)
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
FILE * hd_src ; FILE * hd_src ;
int hd ;
struct stat file_info; struct stat file_info;
char *file; char *file;
@@ -72,9 +69,7 @@ int main(int argc, char **argv)
url = argv[2]; url = argv[2];
/* get the file size of the local file */ /* get the file size of the local file */
hd = open(file, O_RDONLY) ; stat(file, &file_info);
fstat(hd, &file_info);
close(hd) ;
/* get a FILE * of the same file, could also be made with /* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just fdopen() from the previous descriptor, but hey this is just

View File

@@ -0,0 +1,111 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if(mem->memory == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
int main(void)
{
CURL *curl;
CURLcode res;
struct MemoryStruct chunk;
static const char *postthis="Field=1&Field=2&Field=3";
chunk.memory = malloc(1); /* will be grown as needed by realloc above */
chunk.size = 0; /* no data at this point */
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.org/");
/* send all data to this function */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
/* some servers don't like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
/* if we don't provide POSTFIELDSIZE, libcurl will strlen() by
itself */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else {
/*
* Now, our chunk.memory points to a memory block that is chunk.size
* bytes big and contains the remote file.
*
* Do something nice with it!
*/
printf("%s\n",chunk.memory);
}
/* always cleanup */
curl_easy_cleanup(curl);
if(chunk.memory)
free(chunk.memory);
/* we're done with libcurl, so clean it up */
curl_global_cleanup();
}
return 0;
}

105
docs/examples/sessioninfo.c Normal file
View File

@@ -0,0 +1,105 @@
/***************************************************************************
* _ _ ____ _
* 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.
*
***************************************************************************/
/* Note that this example currently requires cURL to be linked against
GnuTLS (and this program must also be linked against -lgnutls). */
#include <stdio.h>
#include <curl/curl.h>
#include <gnutls/gnutls.h>
static CURL *curl;
static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream)
{
const struct curl_tlssessioninfo *info;
unsigned int cert_list_size;
const gnutls_datum_t *chainp;
CURLcode res;
(void)stream;
(void)ptr;
res = curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &info);
if(!res) {
switch(info->backend) {
case CURLSSLBACKEND_GNUTLS:
/* info->internals is now the gnutls_session_t */
chainp = gnutls_certificate_get_peers(info->internals, &cert_list_size);
if((chainp) && (cert_list_size)) {
unsigned int i;
for(i = 0; i < cert_list_size; i++) {
gnutls_x509_crt_t cert;
gnutls_datum_t dn;
if(GNUTLS_E_SUCCESS == gnutls_x509_crt_init(&cert)) {
if(GNUTLS_E_SUCCESS ==
gnutls_x509_crt_import(cert, &chainp[i], GNUTLS_X509_FMT_DER)) {
if(GNUTLS_E_SUCCESS ==
gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &dn)) {
fprintf(stderr, "Certificate #%d: %.*s", i, dn.size, dn.data);
gnutls_free(dn.data);
}
}
gnutls_x509_crt_deinit(cert);
}
}
}
break;
case CURLSSLBACKEND_NONE:
default:
break;
}
}
return size * nmemb;
}
int main(void)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wrfu);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
(void) curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}

View File

@@ -22,8 +22,9 @@
/* Example using an in memory PEM user certificate and RSA key to retrieve an /* Example using an in memory PEM user certificate and RSA key to retrieve an
* https page. * https page.
* Written by Ishan SinghLevett, based on Theo Borm's cacertinmem.c. * 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 * Note that to maintain simplicity this example does not use a CA certificate
* if you want a properly secure connection * for peer verification. However, some form of peer verification
* must be used in real circumstances when a secure connection is required.
*/ */
#include <openssl/ssl.h> #include <openssl/ssl.h>
@@ -152,6 +153,18 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
printf("Use Key failed\n"); printf("Use Key failed\n");
} }
/* free resources that have been allocated by openssl functions */
if (bio)
BIO_free(bio);
if (kbio)
BIO_free(kbio);
if (rsa)
RSA_free(rsa);
if (cert)
X509_free(cert);
/* all set to go */ /* all set to go */
return CURLE_OK ; return CURLE_OK ;

View File

@@ -79,9 +79,12 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
curl_multi_assign.pdf curl_easy_pause.pdf curl_easy_recv.pdf \ curl_multi_assign.pdf curl_easy_pause.pdf curl_easy_recv.pdf \
curl_easy_send.pdf curl_multi_socket_action.pdf curl_multi_wait.pdf curl_easy_send.pdf curl_multi_socket_action.pdf curl_multi_wait.pdf
m4macrodir = $(datadir)/aclocal
dist_m4macro_DATA = libcurl.m4
CLEANFILES = $(HTMLPAGES) $(PDFPAGES) CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4 ABI \ EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) ABI \
symbols-in-versions symbols.pl symbols-in-versions symbols.pl
MAN2HTML= roffit --mandir=. < $< >$@ MAN2HTML= roffit --mandir=. < $< >$@

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 .\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms .\" * you should have received as part of this distribution. The terms
@@ -219,8 +219,20 @@ done. The struct reports how many certs it found and then you can extract info
for each of those certs by following the linked lists. The info chain is for each of those certs by following the linked lists. The info chain is
provided in a series of data in the format "name:content" where the content is provided in a series of data in the format "name:content" where the content is
for the specific named data. See also the certinfo.c example. NOTE: this for the specific named data. See also the certinfo.c example. NOTE: this
option is only available in libcurl built with OpenSSL support. (Added in option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL
7.19.1) support. (Added in 7.19.1)
.IP CURLINFO_TLS_SESSION
Pass a pointer to a 'struct curl_tlsinfo *'. The pointer will be initialized
to refer to a 'struct curl_tlsinfo *' that will contain an enum indicating the
SSL library used for the handshake and the respective internal TLS session
structure of this underlying SSL library.
This may then be used to extract certificate information in a format
convenient for further processing, such as manual validation. NOTE: this
option may not be available for all SSL backends; unsupported SSL backends
will return 'CURLSSLBACKEND_NONE' to indicate that they are not supported;
this does not mean that no SSL backend was used. (Added in 7.34.0)
.IP CURLINFO_CONDITION_UNMET .IP CURLINFO_CONDITION_UNMET
Pass a pointer to a long to receive the number 1 if the condition provided in Pass a pointer to a long to receive the number 1 if the condition provided in
the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if

View File

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

View File

@@ -260,9 +260,9 @@ used to fast forward a file in a resumed upload (instead of reading all
uploaded bytes with the normal read function/callback). It is also called to uploaded bytes with the normal read function/callback). It is also called to
rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication rewind a stream when doing a HTTP PUT or POST with a multi-pass authentication
method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET, method. The function shall work like "fseek" or "lseek" and accepted SEEK_SET,
SEEK_CUR and SEEK_END as argument for origin, although (in 7.18.0) libcurl SEEK_CUR and SEEK_END as argument for origin, although libcurl currently only
only passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on passes SEEK_SET. The callback must return 0 (CURL_SEEKFUNC_OK) on success, 1
success, 1 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2 (CURL_SEEKFUNC_FAIL) to cause the upload operation to fail or 2
(CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is (CURL_SEEKFUNC_CANTSEEK) to indicate that while the seek failed, libcurl is
free to work around the problem if possible. The latter can sometimes be done free to work around the problem if possible. The latter can sometimes be done
by instead reading from the input or similar. by instead reading from the input or similar.
@@ -891,6 +891,19 @@ Active Directory server.
For more information about the individual components of a LDAP URL please For more information about the individual components of a LDAP URL please
see RFC4516. see RFC4516.
.B RTMP
There's no official URL spec for RTMP so libcurl uses the URL syntax supported
by the underlying librtmp library. It has a syntax where it wants a
traditional URL, followed by a space and a series of space-separated
name=value pairs.
While space is not typically a "legal" letter, libcurl accepts them. When a
user wants to pass in a '#' (hash) character it will be treated as a fragment
and get cut off by libcurl if provided literally. You will instead have to
escape it by providing it as backslash and its ASCII value in hexadecimal:
"\\23".
.B NOTES .B NOTES
Starting with version 7.20.0, the fragment part of the URI will not be sent as Starting with version 7.20.0, the fragment part of the URI will not be sent as
@@ -1118,7 +1131,7 @@ 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) find a .netrc file in the current user's home directory. (Added in 7.10.9)
.IP CURLOPT_USERPWD .IP CURLOPT_USERPWD
Pass a char * as parameter, pointing to a zero terminated login details string 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]. for the connection. The format of which is: [user name]:[password].
When using NTLM, you can set the domain by prepending it to the user name and 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 separating the domain and name with a forward (/) or backward slash (\\). Like
@@ -1132,15 +1145,18 @@ and password information to hosts using the initial host name (unless
other hosts it will not send the user and password to those. This is enforced other hosts it will not send the user and password to those. This is enforced
to prevent accidental information leakage. 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 Use \fICURLOPT_HTTPAUTH\fP to specify the authentication method for HTTP based
connections. connections or \fICURLOPT_LOGIN_OPTIONS\fP to control IMAP, POP3 and SMTP
options.
The user and password strings are not URL decoded, so there's no way to send
in a user name containing a colon using this option. Use \fCURLOPT_USERNAME\fP
for that, or include it in the URL.
.IP CURLOPT_PROXYUSERPWD .IP CURLOPT_PROXYUSERPWD
Pass a char * as parameter, which should be [user name]:[password] to use for Pass a char * as parameter, which should be [user name]:[password] to use for
the connection to the HTTP proxy. the connection to the HTTP proxy. Both the name and the password will be URL
decoded before use, so to include for example a colon in the user name you
should encode it as %3A.
Use \fICURLOPT_PROXYAUTH\fP to specify the authentication method. Use \fICURLOPT_PROXYAUTH\fP to specify the authentication method.
.IP CURLOPT_USERNAME .IP CURLOPT_USERNAME
@@ -1151,14 +1167,26 @@ user name to use for the transfer.
authentication. You should not use this option together with the (older) authentication. You should not use this option together with the (older)
CURLOPT_USERPWD option. CURLOPT_USERPWD option.
In order to specify the password to be used in conjunction with the user name To specify the password and login options, along with the user name, use the
use the \fICURLOPT_PASSWORD\fP option. (Added in 7.19.1) \fICURLOPT_PASSWORD\fP and \fICURLOPT_LOGIN_OPTIONS\fP options. (Added in
7.19.1)
.IP CURLOPT_PASSWORD .IP CURLOPT_PASSWORD
Pass a char * as parameter, which should be pointing to the zero terminated Pass a char * as parameter, which should be pointing to the zero terminated
password to use for the transfer. password to use for the transfer.
The CURLOPT_PASSWORD option should be used in conjunction with The CURLOPT_PASSWORD option should be used in conjunction with the
the \fICURLOPT_USERNAME\fP option. (Added in 7.19.1) \fICURLOPT_USERNAME\fP option. (Added in 7.19.1)
.IP CURLOPT_LOGIN_OPTIONS
(Added in 7.34.0) Pass a char * as parameter, which should be pointing to the
zero terminated options string to use for the transfer.
At present only IMAP, POP3 and SMTP support login options. For more
information about the login options please see RFC2384, RFC5092 and IETF draft
draft-earhart-url-smtp-00.txt
\CURLOPT_LOGIN_OPTIONS\fP can be used to set protocol specific login options,
such as the preferred authentication mechanism via "AUTH=NTLM" or "AUTH=*",
and should be used in conjunction with the \fICURLOPT_USERNAME\fP option.
.IP CURLOPT_PROXYUSERNAME .IP CURLOPT_PROXYUSERNAME
Pass a char * as parameter, which should be pointing to the zero terminated Pass a char * as parameter, which should be pointing to the zero terminated
user name to use for the transfer while connecting to Proxy. user name to use for the transfer while connecting to Proxy.
@@ -1289,6 +1317,13 @@ mechanisms and to the IMAP, POP3 and SMTP protocols. (Added in 7.31.0)
Note: Whilst IMAP supports this option there is no need to explicitly set it, 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 as libcurl can determine the feature itself when the server supports the
SASL-IR CAPABILITY. SASL-IR CAPABILITY.
.IP CURLOPT_BEARER
Pass a char * as parameter, which should point to the zero terminated OAUTH
2.0 Bearer Access Token for use with IMAP. POP3 and SMTP servers that support
the OAUTH 2.0 Authorization Framework. (Added in 7.33.0)
Note: The user name used to generate the Bearer Token should be supplied via
the \fICURLOPT_USERNAME\fP option.
.SH HTTP OPTIONS .SH HTTP OPTIONS
.IP CURLOPT_AUTOREFERER .IP CURLOPT_AUTOREFERER
Pass a parameter set to 1 to enable this. When enabled, libcurl will Pass a parameter set to 1 to enable this. When enabled, libcurl will
@@ -1631,12 +1666,18 @@ SMTP mail request. The linked list should be a fully valid list of \fBstruct
curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to curl_slist\fP structs properly filled in. Use \fIcurl_slist_append(3)\fP to
create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire list. create the list and \fIcurl_slist_free_all(3)\fP to clean up an entire list.
Each recipient should be specified within a pair of angled brackets (<>), When performing a mail transfer, each recipient should be specified within a
however, should you not use an angled bracket as the first character libcurl pair of angled brackets (<>), however, should you not use an angled bracket as
will assume you provided a single email address and enclose that address the first character libcurl will assume you provided a single email address and
within brackets for you. enclose that address within brackets for you. (Added in 7.20.0)
(Added in 7.20.0) When performing an address verification (VRFY command), each recipient should
be specified as the user name or user name and domain (as per Section 3.5 of
RFC5321). (Added in 7.34.0)
When performing a mailing list expand (EXPN command), each recipient should be
specified using the mailing list name, such as "Friends" or "London-Office".
(Added in 7.34.0)
.IP CURLOPT_MAIL_AUTH .IP CURLOPT_MAIL_AUTH
Pass a pointer to a zero terminated string as parameter. This will be used Pass a pointer to a zero terminated string as parameter. This will be used
to specify the authentication address (identity) of a submitted message that to specify the authentication address (identity) of a submitted message that
@@ -2008,35 +2049,32 @@ source file to the remote target file.
Pass a curl_off_t as parameter. It contains the offset in number of bytes that Pass a curl_off_t as parameter. It contains the offset in number of bytes that
you want the transfer to start from. (Added in 7.11.0) you want the transfer to start from. (Added in 7.11.0)
.IP CURLOPT_CUSTOMREQUEST .IP CURLOPT_CUSTOMREQUEST
Pass a pointer to a zero terminated string as parameter. It can be used to Pass a pointer to a zero terminated string as parameter.
specify the request instead of GET or HEAD when performing HTTP based
requests, instead of LIST and NLST when performing FTP directory listings and
instead of LIST and RETR when issuing POP3 based commands. This is
particularly useful, for example, for performing a HTTP DELETE request or a
POP3 DELE command.
Please don't perform this at will, on HTTP based requests, by making sure
your server supports the command you are sending first.
When you change the request method by setting \fBCURLOPT_CUSTOMREQUEST\fP to When you change the request method by setting \fBCURLOPT_CUSTOMREQUEST\fP to
something, you don't actually change how libcurl behaves or acts in regards something, you don't actually change how libcurl behaves or acts in regards
to the particular request method, it will only change the actual string sent to the particular request method, it will only change the actual string sent
in the request. in the request.
Restore to the internal default by setting this to NULL.
This option can be used to specify the request:
.B HTTP
Instead of GET or HEAD when performing HTTP based requests. This is
particularly useful, for example, for performing a HTTP DELETE request.
For example: For example:
With the HTTP protocol when you tell libcurl to do a HEAD request, but then When you tell libcurl to do a HEAD request, but then specify a GET though a
specify a GET though a custom request libcurl will still act as if it sent a custom request libcurl will still act as if it sent a HEAD. To switch to a
HEAD. To switch to a proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a proper POST use
proper POST use \fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch \fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch to a proper GET
to a proper GET use CURLOPT_HTTPGET. use CURLOPT_HTTPGET.
With the POP3 protocol when you tell libcurl to use a custom request it will Please don't perform this at will, on HTTP based requests, by making sure
behave like a LIST or RETR command was sent where it expects data to be your server supports the command you are sending first.
returned by the server. As such \fICURLOPT_NOBODY\fP should be used when
specifying commands such as DELE and NOOP for example.
Restore to the internal default by setting this to NULL.
Many people have wrongly used this option to replace the entire request with Many people have wrongly used this option to replace the entire request with
their own, including multiple headers and POST contents. While that might their own, including multiple headers and POST contents. While that might
@@ -2046,7 +2084,35 @@ could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and
replace or extend the set of headers sent by libcurl. Use replace or extend the set of headers sent by libcurl. Use
\fICURLOPT_HTTP_VERSION\fP to change HTTP version. \fICURLOPT_HTTP_VERSION\fP to change HTTP version.
(Support for POP3 added in 7.26.0) .B FTP
Instead of LIST and NLST when performing FTP directory listings.
.B IMAP
Instead of LIST when issuing IMAP based requests. (Added in 7.30.0)
.B POP3
Instead of LIST and RETR when issuing POP3 based requests. (Added in 7.26.0)
For example:
When you tell libcurl to use a custom request it will behave like a LIST or
RETR command was sent where it expects data to be returned by the server. As
such \fICURLOPT_NOBODY\fP should be used when specifying commands such as
DELE and NOOP for example.
.B SMTP
Instead of a HELP or VRFY when issuing SMTP based requests. (Added in 7.34.0)
For example:
Normally a multiline response is returned which can be used, in conjuection with
\fICURLOPT_MAIL_RCPT\fP, to specify an EXPN request. If the \fICURLOPT_NOBODY\fP
option is specified then the request can be used to issue NOOP and RSET
commands.
.IP CURLOPT_FILETIME .IP CURLOPT_FILETIME
Pass a long. If it is 1, libcurl will attempt to get the modification date of Pass a long. If it is 1, libcurl will attempt to get the modification date of
the remote document in this operation. This requires that the remote server the remote document in this operation. This requires that the remote server
@@ -2142,10 +2208,14 @@ In unix-like systems, this might cause signals to be used unless
Default timeout is 0 (zero) which means it never times out. Default timeout is 0 (zero) which means it never times out.
.IP CURLOPT_TIMEOUT_MS .IP CURLOPT_TIMEOUT_MS
Like \fICURLOPT_TIMEOUT\fP but takes number of milliseconds instead. If An alternative to \fICURLOPT_TIMEOUT\fP but takes number of milliseconds
libcurl is built to use the standard system name resolver, that portion instead. If libcurl is built to use the standard system name resolver, that
of the transfer will still use full-second resolution for timeouts with portion of the transfer will still use full-second resolution for timeouts
a minimum timeout allowed of one second. with a minimum timeout allowed of one second.
If both \fICURLOPT_TIMEOUT\fP and \fICURLOPT_TIMEOUT_MS\fP are set, the value
set last will be used.
(Added in 7.16.2) (Added in 7.16.2)
.IP CURLOPT_LOW_SPEED_LIMIT .IP CURLOPT_LOW_SPEED_LIMIT
Pass a long as parameter. It contains the transfer speed in bytes per second Pass a long as parameter. It contains the transfer speed in bytes per second
@@ -2269,7 +2339,9 @@ ADDRESS can of course be either IPv4 or IPv6 style addressing.
This option effectively pre-populates the DNS cache with entries for the This option effectively pre-populates the DNS cache with entries for the
host+port pair so redirects and everything that operations against the host+port pair so redirects and everything that operations against the
HOST+PORT will instead use your provided ADDRESS. HOST+PORT will instead use your provided ADDRESS. Addresses to set with
\fICURL_RESOLVE\fP will not time-out from the DNS cache like ordindary
entries.
You can remove names from the DNS cache again, to stop providing these fake You can remove names from the DNS cache again, to stop providing these fake
resolves, by including a string in the linked list that uses the format resolves, by including a string in the linked list that uses the format
@@ -2291,6 +2363,36 @@ This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one. supports this operation. The c-ares backend is the only such one.
(Added in 7.24.0) (Added in 7.24.0)
.IP CURLOPT_DNS_INTERFACE
Pass a char * as parameter. Set the name of the network interface that
the DNS resolver should bind to. This must be an interface name (not an
address). Set this option to NULL to use the default setting (don't
bind to a specific interface).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.33.0)
.IP CURLOPT_DNS_LOCAL_IP4
Set the local IPv4 address that the resolver should bind to. The argument
should be of type char * and contain a single IPv4 address as a string.
Set this option to NULL to use the default setting (don't
bind to a specific IP address).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.33.0)
.IP CURLOPT_DNS_LOCAL_IP6
Set the local IPv6 address that the resolver should bind to. The argument
should be of type char * and contain a single IPv6 address as a string.
Set this option to NULL to use the default setting (don't
bind to a specific IP address).
This option requires that libcurl was built with a resolver backend that
supports this operation. The c-ares backend is the only such one.
(Added in 7.33.0)
.IP CURLOPT_ACCEPTTIMEOUT_MS .IP CURLOPT_ACCEPTTIMEOUT_MS
Pass a long telling libcurl the maximum number of milliseconds to wait for a Pass a long telling libcurl the maximum number of milliseconds to wait for a
server to connect back to libcurl when an active FTP connection is used. If no server to connect back to libcurl when an active FTP connection is used. If no
@@ -2298,22 +2400,20 @@ timeout is set, the internal default of 60000 will be used. (Added in 7.24.0)
.SH SSL and SECURITY OPTIONS .SH SSL and SECURITY OPTIONS
.IP CURLOPT_SSLCERT .IP CURLOPT_SSLCERT
Pass a pointer to a zero terminated string as parameter. The string should be Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your certificate. The default format is "PEM" and can be the file name of your certificate. The default format is "P12" on Secure
changed with \fICURLOPT_SSLCERTTYPE\fP. Transport and "PEM" on other engines, and can be changed with
\fICURLOPT_SSLCERTTYPE\fP.
With NSS this can also be the nickname of the certificate you wish to With NSS or Secure Transport, this can also be the nickname of the certificate
authenticate with. If you want to use a file from the current directory, please you wish to authenticate with as it is named in the security database. If you
precede it with "./" prefix, in order to avoid confusion with a nickname. 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 .IP CURLOPT_SSLCERTTYPE
Pass a pointer to a zero terminated string as parameter. The string should be 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 the format of your certificate. Supported formats are "PEM" and "DER", except
in 7.9.3) with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
(on iOS 5 or later, or OS X 10.7 or later) also support "P12" for
PKCS#12-encoded files. (Added in 7.9.3)
.IP CURLOPT_SSLKEY .IP CURLOPT_SSLKEY
Pass a pointer to a zero terminated string as parameter. The string should be 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 the file name of your private key. The default format is "PEM" and can be
@@ -2321,7 +2421,7 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
(iOS and Mac OS X only) This option is ignored if curl was built against Secure (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 Transport. Secure Transport expects the private key to be already present in
the keychain containing the certificate. the keychain or PKCS#12 file containing the certificate.
.IP CURLOPT_SSLKEYTYPE .IP CURLOPT_SSLKEYTYPE
Pass a pointer to a zero terminated string as parameter. The string should be 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". the format of your private key. Supported formats are "PEM", "DER" and "ENG".
@@ -2358,6 +2458,8 @@ Even though this option doesn't need any parameter, in some configurations
arguments. Therefore, it's recommended to pass 1 as parameter to this option. arguments. Therefore, it's recommended to pass 1 as parameter to this option.
.IP CURLOPT_SSLVERSION .IP CURLOPT_SSLVERSION
Pass a long as parameter to control what version of SSL/TLS to attempt to use. Pass a long as parameter to control what version of SSL/TLS to attempt to use.
(Added in 7.9.2)
The available options are: The available options are:
.RS .RS
.IP CURL_SSLVERSION_DEFAULT .IP CURL_SSLVERSION_DEFAULT
@@ -2365,11 +2467,17 @@ The default action. This will attempt to figure out the remote SSL protocol
version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled
by default with 7.18.1). by default with 7.18.1).
.IP CURL_SSLVERSION_TLSv1 .IP CURL_SSLVERSION_TLSv1
Force TLSv1 Force TLSv1.x
.IP CURL_SSLVERSION_SSLv2 .IP CURL_SSLVERSION_SSLv2
Force SSLv2 Force SSLv2
.IP CURL_SSLVERSION_SSLv3 .IP CURL_SSLVERSION_SSLv3
Force SSLv3 Force SSLv3
.IP CURL_SSLVERSION_TLSv1_0
Force TLSv1.0 (Added in 7.34.0)
.IP CURL_SSLVERSION_TLSv1_1
Force TLSv1.1 (Added in 7.34.0)
.IP CURL_SSLVERSION_TLSv1_2
Force TLSv1.2 (Added in 7.34.0)
.RE .RE
.IP CURLOPT_SSL_VERIFYPEER .IP CURLOPT_SSL_VERIFYPEER
Pass a long as parameter. By default, curl assumes a value of 1. Pass a long as parameter. By default, curl assumes a value of 1.
@@ -2470,9 +2578,10 @@ Curl considers the server the intended one when the Common Name field or a
Subject Alternate Name field in the certificate matches the host name in the Subject Alternate Name field in the certificate matches the host name in the
URL to which you told Curl to connect. URL to which you told Curl to connect.
When the value is 1, libcurl will return a failure. It was previously (in When the value is 1, \fIcurl_easy_setopt\fP will return an error and the option
7.28.0 and earlier) a debug option of some sorts, but it is no longer value will not be changed. It was previously (in 7.28.0 and earlier) a debug
supported due to frequently leading to programmer mistakes. option of some sorts, but it is no longer supported due to frequently leading
to programmer mistakes.
When the value is 0, the connection succeeds regardless of the names in the When the value is 0, the connection succeeds regardless of the names in the
certificate. certificate.
@@ -2482,14 +2591,14 @@ The default value for this option is 2.
This option controls checking the server's certificate's claimed identity. This option controls checking the server's certificate's claimed identity.
The server could be lying. To control lying, see The server could be lying. To control lying, see
\fICURLOPT_SSL_VERIFYPEER\fP. If libcurl is built against NSS and \fICURLOPT_SSL_VERIFYPEER\fP. If libcurl is built against NSS and
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP \fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP is also set
is ignored. to zero and cannot be overridden.
.IP CURLOPT_CERTINFO .IP CURLOPT_CERTINFO
Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With
this enabled, libcurl (if built with OpenSSL) will extract lots of information this enabled, libcurl (if built with OpenSSL, NSS, GSKit or QsoSSL) will
extract lots of information
and data about the certificates in the certificate chain used in the SSL and data about the certificates in the certificate chain used in the SSL
connection. This data is then possible to extract after a transfer using connection. This data may then be retrieved after a transfer using
\fIcurl_easy_getinfo(3)\fP and its option \fICURLINFO_CERTINFO\fP. (Added in \fIcurl_easy_getinfo(3)\fP and its option \fICURLINFO_CERTINFO\fP. (Added in
7.19.1) 7.19.1)
.IP CURLOPT_RANDOM_FILE .IP CURLOPT_RANDOM_FILE

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 .\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms .\" * you should have received as part of this distribution. The terms
@@ -273,6 +273,9 @@ The passed-in socket is not a valid one that libcurl already knows about.
.IP "CURLM_UNKNOWN_OPTION (6)" .IP "CURLM_UNKNOWN_OPTION (6)"
curl_multi_setopt() with unsupported option curl_multi_setopt() with unsupported option
(Added in 7.15.4) (Added in 7.15.4)
.IP "CURLM_ADDED_ALREADY (7)"
An easy handle already added to a multi handle was attempted to get added a
second time. (Added in 7.32.1)
.SH "CURLSHcode" .SH "CURLSHcode"
The "share" interface will return a CURLSHcode to indicate when an error has The "share" interface will return a CURLSHcode to indicate when an error has
occurred. Also consider \fIcurl_share_strerror(3)\fP. occurred. Also consider \fIcurl_share_strerror(3)\fP.

View File

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

View File

@@ -85,8 +85,8 @@ CURLE_LDAP_SEARCH_FAILED 7.1
CURLE_LIBRARY_NOT_FOUND 7.1 7.17.0 CURLE_LIBRARY_NOT_FOUND 7.1 7.17.0
CURLE_LOGIN_DENIED 7.13.1 CURLE_LOGIN_DENIED 7.13.1
CURLE_MALFORMAT_USER 7.1 7.17.0 CURLE_MALFORMAT_USER 7.1 7.17.0
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
CURLE_NOT_BUILT_IN 7.21.5 CURLE_NOT_BUILT_IN 7.21.5
CURLE_NO_CONNECTION_AVAILABLE 7.30.0
CURLE_OK 7.1 CURLE_OK 7.1
CURLE_OPERATION_TIMEDOUT 7.10.2 CURLE_OPERATION_TIMEDOUT 7.10.2
CURLE_OPERATION_TIMEOUTED 7.1 7.17.0 CURLE_OPERATION_TIMEOUTED 7.1 7.17.0
@@ -250,6 +250,7 @@ CURLINFO_SSL_VERIFYRESULT 7.5
CURLINFO_STARTTRANSFER_TIME 7.9.2 CURLINFO_STARTTRANSFER_TIME 7.9.2
CURLINFO_STRING 7.4.1 CURLINFO_STRING 7.4.1
CURLINFO_TEXT 7.9.6 CURLINFO_TEXT 7.9.6
CURLINFO_TLS_SESSION 7.34.0
CURLINFO_TOTAL_TIME 7.4.1 CURLINFO_TOTAL_TIME 7.4.1
CURLINFO_TYPEMASK 7.4.1 CURLINFO_TYPEMASK 7.4.1
CURLIOCMD_NOP 7.12.3 CURLIOCMD_NOP 7.12.3
@@ -270,10 +271,10 @@ CURLKHTYPE_RSA1 7.19.6
CURLKHTYPE_UNKNOWN 7.19.6 CURLKHTYPE_UNKNOWN 7.19.6
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0 CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0 CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0
CURLMOPT_MAXCONNECTS 7.16.3
CURLMOPT_MAX_HOST_CONNECTIONS 7.30.0 CURLMOPT_MAX_HOST_CONNECTIONS 7.30.0
CURLMOPT_MAX_PIPELINE_LENGTH 7.30.0 CURLMOPT_MAX_PIPELINE_LENGTH 7.30.0
CURLMOPT_MAX_TOTAL_CONNECTIONS 7.30.0 CURLMOPT_MAX_TOTAL_CONNECTIONS 7.30.0
CURLMOPT_MAXCONNECTS 7.16.3
CURLMOPT_PIPELINING 7.16.0 CURLMOPT_PIPELINING 7.16.0
CURLMOPT_PIPELINING_SERVER_BL 7.30.0 CURLMOPT_PIPELINING_SERVER_BL 7.30.0
CURLMOPT_PIPELINING_SITE_BL 7.30.0 CURLMOPT_PIPELINING_SITE_BL 7.30.0
@@ -283,6 +284,7 @@ CURLMOPT_TIMERDATA 7.16.0
CURLMOPT_TIMERFUNCTION 7.16.0 CURLMOPT_TIMERFUNCTION 7.16.0
CURLMSG_DONE 7.9.6 CURLMSG_DONE 7.9.6
CURLMSG_NONE 7.9.6 CURLMSG_NONE 7.9.6
CURLM_ADDED_ALREADY 7.32.1
CURLM_BAD_EASY_HANDLE 7.9.6 CURLM_BAD_EASY_HANDLE 7.9.6
CURLM_BAD_HANDLE 7.9.6 CURLM_BAD_HANDLE 7.9.6
CURLM_BAD_SOCKET 7.15.4 CURLM_BAD_SOCKET 7.15.4
@@ -331,6 +333,9 @@ CURLOPT_DEBUGDATA 7.9.6
CURLOPT_DEBUGFUNCTION 7.9.6 CURLOPT_DEBUGFUNCTION 7.9.6
CURLOPT_DIRLISTONLY 7.17.0 CURLOPT_DIRLISTONLY 7.17.0
CURLOPT_DNS_CACHE_TIMEOUT 7.9.3 CURLOPT_DNS_CACHE_TIMEOUT 7.9.3
CURLOPT_DNS_INTERFACE 7.33.0
CURLOPT_DNS_LOCAL_IP4 7.33.0
CURLOPT_DNS_LOCAL_IP6 7.33.0
CURLOPT_DNS_SERVERS 7.24.0 CURLOPT_DNS_SERVERS 7.24.0
CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1 CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1
CURLOPT_EGDSOCKET 7.7 CURLOPT_EGDSOCKET 7.7
@@ -390,6 +395,7 @@ CURLOPT_KRB4LEVEL 7.3 7.17.0
CURLOPT_KRBLEVEL 7.16.4 CURLOPT_KRBLEVEL 7.16.4
CURLOPT_LOCALPORT 7.15.2 CURLOPT_LOCALPORT 7.15.2
CURLOPT_LOCALPORTRANGE 7.15.2 CURLOPT_LOCALPORTRANGE 7.15.2
CURLOPT_LOGIN_OPTIONS 7.34.0
CURLOPT_LOW_SPEED_LIMIT 7.1 CURLOPT_LOW_SPEED_LIMIT 7.1
CURLOPT_LOW_SPEED_TIME 7.1 CURLOPT_LOW_SPEED_TIME 7.1
CURLOPT_MAIL_AUTH 7.25.0 CURLOPT_MAIL_AUTH 7.25.0
@@ -527,6 +533,7 @@ CURLOPT_WRITEHEADER 7.1
CURLOPT_WRITEINFO 7.1 CURLOPT_WRITEINFO 7.1
CURLOPT_XFERINFODATA 7.32.0 CURLOPT_XFERINFODATA 7.32.0
CURLOPT_XFERINFOFUNCTION 7.32.0 CURLOPT_XFERINFOFUNCTION 7.32.0
CURLOPT_XOAUTH2_BEARER 7.33.0
CURLPAUSE_ALL 7.18.0 CURLPAUSE_ALL 7.18.0
CURLPAUSE_CONT 7.18.0 CURLPAUSE_CONT 7.18.0
CURLPAUSE_RECV 7.18.0 CURLPAUSE_RECV 7.18.0
@@ -588,6 +595,16 @@ CURLSSH_AUTH_KEYBOARD 7.16.1
CURLSSH_AUTH_NONE 7.16.1 CURLSSH_AUTH_NONE 7.16.1
CURLSSH_AUTH_PASSWORD 7.16.1 CURLSSH_AUTH_PASSWORD 7.16.1
CURLSSH_AUTH_PUBLICKEY 7.16.1 CURLSSH_AUTH_PUBLICKEY 7.16.1
CURLSSLBACKEND_CYASSL 7.34.0
CURLSSLBACKEND_DARWINSSL 7.34.0
CURLSSLBACKEND_GNUTLS 7.34.0
CURLSSLBACKEND_GSKIT 7.34.0
CURLSSLBACKEND_NONE 7.34.0
CURLSSLBACKEND_NSS 7.34.0
CURLSSLBACKEND_OPENSSL 7.34.0
CURLSSLBACKEND_POLARSSL 7.34.0
CURLSSLBACKEND_QSOSSL 7.34.0
CURLSSLBACKEND_SCHANNEL 7.34.0
CURLSSLOPT_ALLOW_BEAST 7.25.0 CURLSSLOPT_ALLOW_BEAST 7.25.0
CURLUSESSL_ALL 7.17.0 CURLUSESSL_ALL 7.17.0
CURLUSESSL_CONTROL 7.17.0 CURLUSESSL_CONTROL 7.17.0
@@ -620,14 +637,15 @@ CURL_FORMADD_NULL 7.9.8
CURL_FORMADD_OK 7.9.8 CURL_FORMADD_OK 7.9.8
CURL_FORMADD_OPTION_TWICE 7.9.8 CURL_FORMADD_OPTION_TWICE 7.9.8
CURL_FORMADD_UNKNOWN_OPTION 7.9.8 CURL_FORMADD_UNKNOWN_OPTION 7.9.8
CURL_GLOBAL_ACK_EINTR 7.30.0
CURL_GLOBAL_ALL 7.8 CURL_GLOBAL_ALL 7.8
CURL_GLOBAL_DEFAULT 7.8 CURL_GLOBAL_DEFAULT 7.8
CURL_GLOBAL_NOTHING 7.8 CURL_GLOBAL_NOTHING 7.8
CURL_GLOBAL_SSL 7.8 CURL_GLOBAL_SSL 7.8
CURL_GLOBAL_WIN32 7.8.1 CURL_GLOBAL_WIN32 7.8.1
CURL_GLOBAL_ACK_EINTR 7.30.0
CURL_HTTP_VERSION_1_0 7.9.1 CURL_HTTP_VERSION_1_0 7.9.1
CURL_HTTP_VERSION_1_1 7.9.1 CURL_HTTP_VERSION_1_1 7.9.1
CURL_HTTP_VERSION_2_0 7.33.0
CURL_HTTP_VERSION_NONE 7.9.1 CURL_HTTP_VERSION_NONE 7.9.1
CURL_IPRESOLVE_V4 7.10.8 CURL_IPRESOLVE_V4 7.10.8
CURL_IPRESOLVE_V6 7.10.8 CURL_IPRESOLVE_V6 7.10.8
@@ -689,6 +707,9 @@ CURL_SSLVERSION_DEFAULT 7.9.2
CURL_SSLVERSION_SSLv2 7.9.2 CURL_SSLVERSION_SSLv2 7.9.2
CURL_SSLVERSION_SSLv3 7.9.2 CURL_SSLVERSION_SSLv3 7.9.2
CURL_SSLVERSION_TLSv1 7.9.2 CURL_SSLVERSION_TLSv1 7.9.2
CURL_SSLVERSION_TLSv1_0 7.34.0
CURL_SSLVERSION_TLSv1_1 7.34.0
CURL_SSLVERSION_TLSv1_2 7.34.0
CURL_TIMECOND_IFMODSINCE 7.9.7 CURL_TIMECOND_IFMODSINCE 7.9.7
CURL_TIMECOND_IFUNMODSINCE 7.9.7 CURL_TIMECOND_IFUNMODSINCE 7.9.7
CURL_TIMECOND_LASTMOD 7.9.7 CURL_TIMECOND_LASTMOD 7.9.7
@@ -700,6 +721,7 @@ CURL_VERSION_CONV 7.15.4
CURL_VERSION_CURLDEBUG 7.19.6 CURL_VERSION_CURLDEBUG 7.19.6
CURL_VERSION_DEBUG 7.10.6 CURL_VERSION_DEBUG 7.10.6
CURL_VERSION_GSSNEGOTIATE 7.10.6 CURL_VERSION_GSSNEGOTIATE 7.10.6
CURL_VERSION_HTTP2 7.33.0
CURL_VERSION_IDN 7.12.0 CURL_VERSION_IDN 7.12.0
CURL_VERSION_IPV6 7.10 CURL_VERSION_IPV6 7.10
CURL_VERSION_KERBEROS4 7.10 CURL_VERSION_KERBEROS4 7.10

View File

@@ -69,7 +69,7 @@
require it! */ require it! */
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || \ defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
#include <sys/select.h> #include <sys/select.h>
#endif #endif
@@ -645,16 +645,18 @@ typedef enum {
#define CURL_ERROR_SIZE 256 #define CURL_ERROR_SIZE 256
enum curl_khtype {
CURLKHTYPE_UNKNOWN,
CURLKHTYPE_RSA1,
CURLKHTYPE_RSA,
CURLKHTYPE_DSS
};
struct curl_khkey { struct curl_khkey {
const char *key; /* points to a zero-terminated string encoded with base64 const char *key; /* points to a zero-terminated string encoded with base64
if len is zero, otherwise to the "raw" data */ if len is zero, otherwise to the "raw" data */
size_t len; size_t len;
enum type { enum curl_khtype keytype;
CURLKHTYPE_UNKNOWN,
CURLKHTYPE_RSA1,
CURLKHTYPE_RSA,
CURLKHTYPE_DSS
} keytype;
}; };
/* this is the set of return values expected from the curl_sshkeycallback /* this is the set of return values expected from the curl_sshkeycallback
@@ -825,10 +827,10 @@ typedef enum {
/* Name of proxy to use. */ /* Name of proxy to use. */
CINIT(PROXY, OBJECTPOINT, 4), CINIT(PROXY, OBJECTPOINT, 4),
/* "name:password" to use when fetching. */ /* "user:password;options" to use when fetching. */
CINIT(USERPWD, OBJECTPOINT, 5), CINIT(USERPWD, OBJECTPOINT, 5),
/* "name:password" to use with proxy. */ /* "user:password" to use with proxy. */
CINIT(PROXYUSERPWD, OBJECTPOINT, 6), CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
/* Range to get, specified as an ASCII string. */ /* Range to get, specified as an ASCII string. */
@@ -1386,8 +1388,7 @@ typedef enum {
CINIT(ADDRESS_SCOPE, LONG, 171), CINIT(ADDRESS_SCOPE, LONG, 171),
/* Collect certificate chain info and allow it to get retrievable with /* Collect certificate chain info and allow it to get retrievable with
CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only CURLINFO_CERTINFO after the transfer is complete. */
working with OpenSSL-powered builds. */
CINIT(CERTINFO, LONG, 172), CINIT(CERTINFO, LONG, 172),
/* "name" and "pwd" to use when fetching. */ /* "name" and "pwd" to use when fetching. */
@@ -1551,6 +1552,25 @@ typedef enum {
* prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
/* The XOAUTH2 bearer token */
CINIT(XOAUTH2_BEARER, OBJECTPOINT, 220),
/* Set the interface string to use as outgoing network
* interface for DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_INTERFACE, OBJECTPOINT, 221),
/* Set the local IPv4 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP4, OBJECTPOINT, 222),
/* Set the local IPv4 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
/* Set authentication options directly */
CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
CURLOPT_LASTENTRY /* the last unused */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;
@@ -1603,6 +1623,7 @@ enum {
for us! */ for us! */
CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */
CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */
CURL_HTTP_VERSION_2_0, /* please use HTTP 2.0 in the request */
CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
}; };
@@ -1640,9 +1661,12 @@ enum CURL_NETRC_OPTION {
enum { enum {
CURL_SSLVERSION_DEFAULT, CURL_SSLVERSION_DEFAULT,
CURL_SSLVERSION_TLSv1, CURL_SSLVERSION_TLSv1, /* TLS 1.x */
CURL_SSLVERSION_SSLv2, CURL_SSLVERSION_SSLv2,
CURL_SSLVERSION_SSLv3, CURL_SSLVERSION_SSLv3,
CURL_SSLVERSION_TLSv1_0,
CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2,
CURL_SSLVERSION_LAST /* never use, keep last */ CURL_SSLVERSION_LAST /* never use, keep last */
}; };
@@ -1961,6 +1985,28 @@ struct curl_certinfo {
format "name: value" */ format "name: value" */
}; };
/* enum for the different supported SSL backends */
typedef enum {
CURLSSLBACKEND_NONE = 0,
CURLSSLBACKEND_OPENSSL = 1,
CURLSSLBACKEND_GNUTLS = 2,
CURLSSLBACKEND_NSS = 3,
CURLSSLBACKEND_QSOSSL = 4,
CURLSSLBACKEND_GSKIT = 5,
CURLSSLBACKEND_POLARSSL = 6,
CURLSSLBACKEND_CYASSL = 7,
CURLSSLBACKEND_SCHANNEL = 8,
CURLSSLBACKEND_DARWINSSL = 9
} curl_sslbackend;
/* Information about the SSL library used and the respective internal SSL
handle, which can be used to obtain further information regarding the
connection. Asked for with CURLINFO_TLS_SESSION. */
struct curl_tlssessioninfo {
curl_sslbackend backend;
void *internals;
};
#define CURLINFO_STRING 0x100000 #define CURLINFO_STRING 0x100000
#define CURLINFO_LONG 0x200000 #define CURLINFO_LONG 0x200000
#define CURLINFO_DOUBLE 0x300000 #define CURLINFO_DOUBLE 0x300000
@@ -2012,9 +2058,10 @@ typedef enum {
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
/* Fill in new entries below here! */ /* Fill in new entries below here! */
CURLINFO_LASTONE = 42 CURLINFO_LASTONE = 43
} CURLINFO; } CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2166,6 +2213,7 @@ typedef struct {
#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */ #define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */
#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ #define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */
#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */ #define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */
#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */
/* /*
* NAME curl_version_info() * NAME curl_version_info()

View File

@@ -58,51 +58,52 @@
/* ================================================================ */ /* ================================================================ */
#ifdef CURL_SIZEOF_LONG #ifdef CURL_SIZEOF_LONG
# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" #error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
#endif #endif
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T #ifdef CURL_TYPEOF_CURL_SOCKLEN_T
# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" #error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
#endif #endif
#ifdef CURL_SIZEOF_CURL_SOCKLEN_T #ifdef CURL_SIZEOF_CURL_SOCKLEN_T
# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" #error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
#endif #endif
#ifdef CURL_TYPEOF_CURL_OFF_T #ifdef CURL_TYPEOF_CURL_OFF_T
# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" #error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
#endif #endif
#ifdef CURL_FORMAT_CURL_OFF_T #ifdef CURL_FORMAT_CURL_OFF_T
# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" #error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
#endif #endif
#ifdef CURL_FORMAT_CURL_OFF_TU #ifdef CURL_FORMAT_CURL_OFF_TU
# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" #error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
#endif #endif
#ifdef CURL_FORMAT_OFF_T #ifdef CURL_FORMAT_OFF_T
# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" #error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
#endif #endif
#ifdef CURL_SIZEOF_CURL_OFF_T #ifdef CURL_SIZEOF_CURL_OFF_T
# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" #error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
#endif #endif
#ifdef CURL_SUFFIX_CURL_OFF_T #ifdef CURL_SUFFIX_CURL_OFF_T
# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" #error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
#endif #endif
#ifdef CURL_SUFFIX_CURL_OFF_TU #ifdef CURL_SUFFIX_CURL_OFF_TU
# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" #error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
#endif #endif
@@ -110,71 +111,87 @@
/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ /* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
/* ================================================================ */ /* ================================================================ */
/* Configure process defines this to 1 when it finds out that system */
/* header file ws2tcpip.h must be included by the external interface. */
#cmakedefine CURL_PULL_WS2TCPIP_H
#ifdef CURL_PULL_WS2TCPIP_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
/* Configure process defines this to 1 when it finds out that system */ /* Configure process defines this to 1 when it finds out that system */
/* header file sys/types.h must be included by the external interface. */ /* header file sys/types.h must be included by the external interface. */
#cmakedefine CURL_PULL_SYS_TYPES_H ${CURL_PULL_SYS_TYPES_H} #cmakedefine CURL_PULL_SYS_TYPES_H
#ifdef CURL_PULL_SYS_TYPES_H #ifdef CURL_PULL_SYS_TYPES_H
# include <sys/types.h> # include <sys/types.h>
#endif #endif
/* Configure process defines this to 1 when it finds out that system */ /* Configure process defines this to 1 when it finds out that system */
/* header file stdint.h must be included by the external interface. */ /* header file stdint.h must be included by the external interface. */
#cmakedefine CURL_PULL_STDINT_H ${CURL_PULL_STDINT_H} #cmakedefine CURL_PULL_STDINT_H
#ifdef CURL_PULL_STDINT_H #ifdef CURL_PULL_STDINT_H
# include <stdint.h> # include <stdint.h>
#endif #endif
/* Configure process defines this to 1 when it finds out that system */ /* Configure process defines this to 1 when it finds out that system */
/* header file inttypes.h must be included by the external interface. */ /* header file inttypes.h must be included by the external interface. */
#cmakedefine CURL_PULL_INTTYPES_H ${CURL_PULL_INTTYPES_H} #cmakedefine CURL_PULL_INTTYPES_H
#ifdef CURL_PULL_INTTYPES_H #ifdef CURL_PULL_INTTYPES_H
# include <inttypes.h> # include <inttypes.h>
#endif #endif
/* The size of `long', as computed by sizeof. */ /* Configure process defines this to 1 when it finds out that system */
#cmakedefine CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG} /* header file sys/socket.h must be included by the external interface. */
#cmakedefine CURL_PULL_SYS_SOCKET_H
/* Integral data type used for curl_socklen_t. */ #ifdef CURL_PULL_SYS_SOCKET_H
#cmakedefine CURL_TYPEOF_CURL_SOCKLEN_T ${CURL_TYPEOF_CURL_SOCKLEN_T}
/* on windows socklen_t is in here */
#ifdef _WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h> # include <sys/socket.h>
#endif #endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/poll.h must be included by the external interface. */
#cmakedefine CURL_PULL_SYS_POLL_H
#ifdef CURL_PULL_SYS_POLL_H
# include <sys/poll.h>
#endif
/* The size of `long', as computed by sizeof. */
#define CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG}
/* Integral data type used for curl_socklen_t. */
#define CURL_TYPEOF_CURL_SOCKLEN_T ${CURL_TYPEOF_CURL_SOCKLEN_T}
/* The size of `curl_socklen_t', as computed by sizeof. */
#define CURL_SIZEOF_CURL_SOCKLEN_T ${CURL_SIZEOF_CURL_SOCKLEN_T}
/* Data type definition of curl_socklen_t. */ /* Data type definition of curl_socklen_t. */
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
/* The size of `curl_socklen_t', as computed by sizeof. */
#cmakedefine CURL_SIZEOF_CURL_SOCKLEN_T ${CURL_SIZEOF_CURL_SOCKLEN_T}
/* Signed integral data type used for curl_off_t. */ /* Signed integral data type used for curl_off_t. */
#cmakedefine CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T} #define CURL_TYPEOF_CURL_OFF_T ${CURL_TYPEOF_CURL_OFF_T}
/* Data type definition of curl_off_t. */ /* Data type definition of curl_off_t. */
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
/* curl_off_t formatting string directive without "%" conversion specifier. */ /* curl_off_t formatting string directive without "%" conversion specifier. */
#cmakedefine CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}" #define CURL_FORMAT_CURL_OFF_T "${CURL_FORMAT_CURL_OFF_T}"
/* unsigned curl_off_t formatting string without "%" conversion specifier. */ /* unsigned curl_off_t formatting string without "%" conversion specifier. */
#cmakedefine CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}" #define CURL_FORMAT_CURL_OFF_TU "${CURL_FORMAT_CURL_OFF_TU}"
/* curl_off_t formatting string directive with "%" conversion specifier. */ /* curl_off_t formatting string directive with "%" conversion specifier. */
#cmakedefine CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}" #define CURL_FORMAT_OFF_T "${CURL_FORMAT_OFF_T}"
/* The size of `curl_off_t', as computed by sizeof. */ /* The size of `curl_off_t', as computed by sizeof. */
#cmakedefine CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T} #define CURL_SIZEOF_CURL_OFF_T ${CURL_SIZEOF_CURL_OFF_T}
/* curl_off_t constant suffix. */ /* curl_off_t constant suffix. */
#cmakedefine CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T} #define CURL_SUFFIX_CURL_OFF_T ${CURL_SUFFIX_CURL_OFF_T}
/* unsigned curl_off_t constant suffix. */ /* unsigned curl_off_t constant suffix. */
#cmakedefine CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU} #define CURL_SUFFIX_CURL_OFF_TU ${CURL_SUFFIX_CURL_OFF_TU}
#endif /* __CURL_CURLBUILD_H */ #endif /* __CURL_CURLBUILD_H */

View File

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

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -64,6 +64,8 @@ typedef enum {
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
CURLM_LAST CURLM_LAST
} CURLMcode; } CURLMcode;

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -264,6 +264,12 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
(option) == CURLOPT_RTSP_SESSION_ID || \ (option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \ (option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \ (option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_XOAUTH2_BEARER || \
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DNS_INTERFACE || \
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
(option) == CURLOPT_LOGIN_OPTIONS || \
0) 0)
/* evaluates to true if option takes a curl_write_callback argument */ /* evaluates to true if option takes a curl_write_callback argument */

View File

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

View File

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

31
lib/README.http2 Normal file
View File

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

View File

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

View File

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

View File

@@ -164,7 +164,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
break; break;
default: default:
failf(data, "axTLS only supports TLSv1"); failf(data, "axTLS only supports TLS 1.0 and 1.1, "
"and it cannot be specified which one to use");
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }

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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -40,29 +40,45 @@
static const char table64[]= static const char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void decodeQuantum(unsigned char *dest, const char *src) static size_t decodeQuantum(unsigned char *dest, const char *src)
{ {
size_t padding = 0;
const char *s, *p; const char *s, *p;
unsigned long i, v, x = 0; unsigned long i, v, x = 0;
for(i = 0, s = src; i < 4; i++, s++) { for(i = 0, s = src; i < 4; i++, s++) {
v = 0; v = 0;
p = table64;
while(*p && (*p != *s)) { if(*s == '=') {
v++;
p++;
}
if(*p == *s)
x = (x << 6) + v;
else if(*s == '=')
x = (x << 6); x = (x << 6);
padding++;
}
else {
p = table64;
while(*p && (*p != *s)) {
v++;
p++;
}
if(*p == *s)
x = (x << 6) + v;
else
return 0;
}
} }
dest[2] = curlx_ultouc(x & 0xFFUL); if(padding < 1)
dest[2] = curlx_ultouc(x & 0xFFUL);
x >>= 8; x >>= 8;
dest[1] = curlx_ultouc(x & 0xFFUL); if(padding < 2)
dest[1] = curlx_ultouc(x & 0xFFUL);
x >>= 8; x >>= 8;
dest[0] = curlx_ultouc(x & 0xFFUL); dest[0] = curlx_ultouc(x & 0xFFUL);
return 3 - padding;
} }
/* /*
@@ -82,58 +98,71 @@ static void decodeQuantum(unsigned char *dest, const char *src)
CURLcode Curl_base64_decode(const char *src, CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen) unsigned char **outptr, size_t *outlen)
{ {
size_t srclen = 0;
size_t length = 0; size_t length = 0;
size_t equalsTerm = 0; size_t padding = 0;
size_t i; size_t i;
size_t result;
size_t numQuantums; size_t numQuantums;
unsigned char lastQuantum[3];
size_t rawlen = 0; size_t rawlen = 0;
unsigned char *pos;
unsigned char *newstr; unsigned char *newstr;
*outptr = NULL; *outptr = NULL;
*outlen = 0; *outlen = 0;
srclen = strlen(src);
/* Check the length of the input string is valid */
if(!srclen || srclen % 4)
return CURLE_BAD_CONTENT_ENCODING;
/* Find the position of any = padding characters */
while((src[length] != '=') && src[length]) while((src[length] != '=') && src[length])
length++; length++;
/* A maximum of two = padding characters is allowed */ /* A maximum of two = padding characters is allowed */
if(src[length] == '=') { if(src[length] == '=') {
equalsTerm++; padding++;
if(src[length+equalsTerm] == '=') if(src[length + 1] == '=')
equalsTerm++; padding++;
} }
numQuantums = (length + equalsTerm) / 4;
/* Don't allocate a buffer if the decoded length is 0 */ /* Check the = padding characters weren't part way through the input */
if(numQuantums == 0) if(length + padding != srclen)
return CURLE_OK; return CURLE_BAD_CONTENT_ENCODING;
rawlen = (numQuantums * 3) - equalsTerm; /* Calculate the number of quantums */
numQuantums = srclen / 4;
/* The buffer must be large enough to make room for the last quantum /* Calculate the size of the decoded string */
(which may be partially thrown out) and the zero terminator. */ rawlen = (numQuantums * 3) - padding;
newstr = malloc(rawlen+4);
/* Allocate our buffer including room for a zero terminator */
newstr = malloc(rawlen + 1);
if(!newstr) if(!newstr)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
*outptr = newstr; pos = newstr;
/* Decode all but the last quantum (which may not decode to a /* Decode the quantums */
multiple of 3 bytes) */ for(i = 0; i < numQuantums; i++) {
for(i = 0; i < numQuantums - 1; i++) { result = decodeQuantum(pos, src);
decodeQuantum(newstr, src); if(!result) {
newstr += 3; src += 4; Curl_safefree(newstr);
return CURLE_BAD_CONTENT_ENCODING;
}
pos += result;
src += 4;
} }
/* This final decode may actually read slightly past the end of the buffer /* Zero terminate */
if the input string is missing pad bytes. This will almost always be *pos = '\0';
harmless. */
decodeQuantum(lastQuantum, src);
for(i = 0; i < 3 - equalsTerm; i++)
newstr[i] = lastQuantum[i];
newstr[i] = '\0'; /* zero terminate */ /* Return the decoded data */
*outptr = newstr;
*outlen = rawlen; /* return size of decoded data */ *outlen = rawlen;
return CURLE_OK; return CURLE_OK;
} }

View File

@@ -529,10 +529,10 @@
#define SEND_TYPE_RETV int #define SEND_TYPE_RETV int
/* Define to use the QsoSSL package. */ /* Define to use the QsoSSL package. */
#define USE_QSOSSL #undef USE_QSOSSL
/* Define to use the GSKit package. */ /* Define to use the GSKit package. */
#undef USE_GSKIT #define USE_GSKIT
/* Use the system keyring as the default CA bundle. */ /* Use the system keyring as the default CA bundle. */
#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB" #define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"

View File

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

View File

@@ -164,8 +164,7 @@ tcpkeepalive(struct SessionHandle *data,
static CURLcode static CURLcode
singleipconnect(struct connectdata *conn, singleipconnect(struct connectdata *conn,
const Curl_addrinfo *ai, /* start connecting to this */ const Curl_addrinfo *ai, /* start connecting to this */
curl_socket_t *sock, curl_socket_t *sock);
bool *connected);
/* /*
* Curl_timeleft() returns the amount of milliseconds left allowed for the * Curl_timeleft() returns the amount of milliseconds left allowed for the
@@ -233,45 +232,6 @@ long Curl_timeleft(struct SessionHandle *data,
return timeout_ms; return timeout_ms;
} }
/*
* checkconnect() checks for a TCP connect on the given socket.
* It returns:
*/
enum chkconn_t {
CHKCONN_SELECT_ERROR = -1,
CHKCONN_CONNECTED = 0,
CHKCONN_IDLE = 1,
CHKCONN_FDSET_ERROR = 2
};
static enum chkconn_t
checkconnect(curl_socket_t sockfd)
{
int rc;
#ifdef mpeix
/* Call this function once now, and ignore the results. We do this to
"clear" the error state on the socket so that we can later read it
reliably. This is reported necessary on the MPE/iX operating system. */
(void)verifyconnect(sockfd, NULL);
#endif
rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 0);
if(-1 == rc)
/* error, no connect here, try next */
return CHKCONN_SELECT_ERROR;
else if(rc & CURL_CSELECT_ERR)
/* error condition caught */
return CHKCONN_FDSET_ERROR;
else if(rc)
return CHKCONN_CONNECTED;
return CHKCONN_IDLE;
}
static CURLcode bindlocal(struct connectdata *conn, static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd, int af) curl_socket_t sockfd, int af)
{ {
@@ -573,42 +533,53 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
more address exists or error */ more address exists or error */
static CURLcode trynextip(struct connectdata *conn, static CURLcode trynextip(struct connectdata *conn,
int sockindex, int sockindex,
bool *connected) int tempindex)
{ {
curl_socket_t sockfd; CURLcode rc = CURLE_COULDNT_CONNECT;
Curl_addrinfo *ai;
/* First clean up after the failed socket. /* First clean up after the failed socket.
Don't close it yet to ensure that the next IP's socket gets a different Don't close it yet to ensure that the next IP's socket gets a different
file descriptor, which can prevent bugs when the curl_multi_socket_action file descriptor, which can prevent bugs when the curl_multi_socket_action
interface is used with certain select() replacements such as kqueue. */ interface is used with certain select() replacements such as kqueue. */
curl_socket_t fd_to_close = conn->sock[sockindex]; curl_socket_t fd_to_close = conn->tempsock[tempindex];
conn->sock[sockindex] = CURL_SOCKET_BAD; conn->tempsock[tempindex] = CURL_SOCKET_BAD;
*connected = FALSE;
if(sockindex != FIRSTSOCKET) { if(sockindex == FIRSTSOCKET) {
Curl_closesocket(conn, fd_to_close); Curl_addrinfo *ai;
return CURLE_COULDNT_CONNECT; /* no next */ int family;
}
/* try the next address */ if(conn->tempaddr[tempindex]) {
ai = conn->ip_addr->ai_next; /* find next address in the same protocol family */
family = conn->tempaddr[tempindex]->ai_family;
while(ai) { ai = conn->tempaddr[tempindex]->ai_next;
CURLcode res = singleipconnect(conn, ai, &sockfd, connected); }
if(res) else {
return res; /* happy eyeballs - try the other protocol family */
if(sockfd != CURL_SOCKET_BAD) { int firstfamily = conn->tempaddr[0]->ai_family;
/* store the new socket descriptor */ family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
conn->sock[sockindex] = sockfd; ai = conn->tempaddr[0]->ai_next;
conn->ip_addr = ai; }
Curl_closesocket(conn, fd_to_close);
return CURLE_OK; while(ai) {
while(ai && ai->ai_family != family)
ai = ai->ai_next;
if(ai) {
rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
conn->tempaddr[tempindex] = ai;
if(rc == CURLE_COULDNT_CONNECT) {
ai = ai->ai_next;
continue;
}
}
break;
} }
ai = ai->ai_next;
} }
Curl_closesocket(conn, fd_to_close);
return CURLE_COULDNT_CONNECT; if(fd_to_close != CURL_SOCKET_BAD)
Curl_closesocket(conn, fd_to_close);
return rc;
} }
/* Copies connection info into the session handle to make it available /* Copies connection info into the session handle to make it available
@@ -707,6 +678,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
error, Curl_strerror(conn, error)); error, Curl_strerror(conn, error));
return; return;
} }
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
if(!getaddressinfo((struct sockaddr*)&ssloc, if(!getaddressinfo((struct sockaddr*)&ssloc,
conn->local_ip, &conn->local_port)) { conn->local_ip, &conn->local_port)) {
@@ -732,11 +704,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
CURLcode code = CURLE_OK; CURLcode code = CURLE_OK;
curl_socket_t sockfd = conn->sock[sockindex]; long allow;
long allow = DEFAULT_CONNECT_TIMEOUT;
int error = 0; int error = 0;
struct timeval now; struct timeval now;
enum chkconn_t chk; int result;
int i;
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
@@ -759,69 +731,104 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT; return CURLE_OPERATION_TIMEDOUT;
} }
/* check socket for connect */ for(i=0; i<2; i++) {
chk = checkconnect(sockfd); if(conn->tempsock[i] == CURL_SOCKET_BAD)
if(CHKCONN_IDLE == chk) { continue;
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
infof(data, "After %ldms connect time, move on!\n", #ifdef mpeix
conn->timeoutms_per_addr); /* Call this function once now, and ignore the results. We do this to
goto next; "clear" the error state on the socket so that we can later read it
reliably. This is reported necessary on the MPE/iX operating system. */
(void)verifyconnect(conn->tempsock[i], NULL);
#endif
/* check socket for connect */
result = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
if(result == 0) { /* no connection yet */
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
infof(data, "After %ldms connect time, move on!\n",
conn->timeoutms_per_addr);
error = ETIMEDOUT;
}
/* should we try another protocol family? */
if(i == 0 && conn->tempaddr[1] == NULL &&
curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
trynextip(conn, sockindex, 1);
}
} }
else if(result == CURL_CSELECT_OUT) {
if(verifyconnect(conn->tempsock[i], &error)) {
/* we are connected with TCP, awesome! */
int other = i ^ 1;
/* not an error, but also no connection yet */ /* use this socket from now on */
return code; conn->sock[sockindex] = conn->tempsock[i];
} conn->ip_addr = conn->tempaddr[i];
conn->tempsock[i] = CURL_SOCKET_BAD;
if(CHKCONN_CONNECTED == chk) { /* close the other socket, if open */
if(verifyconnect(sockfd, &error)) { if(conn->tempsock[other] != CURL_SOCKET_BAD) {
/* we are connected with TCP, awesome! */ Curl_closesocket(conn, conn->tempsock[other]);
conn->tempsock[other] = CURL_SOCKET_BAD;
}
/* see if we need to do any proxy magic first once we connected */ /* see if we need to do any proxy magic first once we connected */
code = Curl_connected_proxy(conn); code = Curl_connected_proxy(conn, sockindex);
if(code) if(code)
return code; return code;
conn->bits.tcpconnect[sockindex] = TRUE; conn->bits.tcpconnect[sockindex] = TRUE;
*connected = TRUE; *connected = TRUE;
if(sockindex == FIRSTSOCKET) if(sockindex == FIRSTSOCKET)
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
Curl_verboseconnect(conn); Curl_updateconninfo(conn, conn->sock[sockindex]);
Curl_updateconninfo(conn, sockfd); Curl_verboseconnect(conn);
return CURLE_OK; return CURLE_OK;
}
else
infof(data, "Connection failed\n");
} }
/* nope, not connected for real */ else if(result & CURL_CSELECT_ERR)
} (void)verifyconnect(conn->tempsock[i], &error);
else {
/* nope, not connected */ /*
if(CHKCONN_FDSET_ERROR == chk) { * The connection failed here, we should attempt to connect to the "next
(void)verifyconnect(sockfd, &error); * address" for the given host. But first remember the latest error.
infof(data, "%s\n",Curl_strerror(conn, error)); */
if(error) {
char ipaddress[MAX_IPADR_LEN];
data->state.os_errno = error;
SET_SOCKERRNO(error);
Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
infof(data, "connect to %s port %ld failed: %s\n",
ipaddress, conn->port, Curl_strerror(conn, error));
conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2;
code = trynextip(conn, sockindex, i);
} }
else
infof(data, "Connection failed\n");
} }
/*
* The connection failed here, we should attempt to connect to the "next
* address" for the given host. But first remember the latest error.
*/
if(error) {
data->state.os_errno = error;
SET_SOCKERRNO(error);
}
next:
conn->timeoutms_per_addr = conn->ip_addr->ai_next == NULL ?
allow : allow / 2;
code = trynextip(conn, sockindex, connected);
if(code) { if(code) {
error = SOCKERRNO; /* no more addresses to try */
data->state.os_errno = error;
failf(data, "Failed connect to %s:%ld; %s", /* if the first address family runs out of addresses to try before
conn->host.name, conn->port, Curl_strerror(conn, error)); the happy eyeball timeout, go ahead and try the next family now */
if(conn->tempaddr[1] == NULL) {
int rc;
rc = trynextip(conn, sockindex, 1);
if(rc == CURLE_OK)
return CURLE_OK;
}
failf(data, "Failed to connect to %s port %ld: %s",
conn->bits.proxy?conn->proxy.name:conn->host.name,
conn->port, Curl_strerror(conn, error));
} }
return code; return code;
@@ -938,8 +945,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
static CURLcode static CURLcode
singleipconnect(struct connectdata *conn, singleipconnect(struct connectdata *conn,
const Curl_addrinfo *ai, const Curl_addrinfo *ai,
curl_socket_t *sockp, curl_socket_t *sockp)
bool *connected)
{ {
struct Curl_sockaddr_ex addr; struct Curl_sockaddr_ex addr;
int rc; int rc;
@@ -948,9 +954,10 @@ singleipconnect(struct connectdata *conn,
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
curl_socket_t sockfd; curl_socket_t sockfd;
CURLcode res = CURLE_OK; CURLcode res = CURLE_OK;
char ipaddress[MAX_IPADR_LEN];
long port;
*sockp = CURL_SOCKET_BAD; *sockp = CURL_SOCKET_BAD;
*connected = FALSE; /* default is not connected */
res = Curl_socket(conn, ai, &addr, &sockfd); res = Curl_socket(conn, ai, &addr, &sockfd);
if(res) if(res)
@@ -961,7 +968,7 @@ singleipconnect(struct connectdata *conn,
/* store remote address and port used in this connection attempt */ /* store remote address and port used in this connection attempt */
if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
conn->primary_ip, &conn->primary_port)) { ipaddress, &port)) {
/* malformed address or bug in inet_ntop, try next address */ /* malformed address or bug in inet_ntop, try next address */
error = ERRNO; error = ERRNO;
failf(data, "sa_addr inet_ntop() failed with errno %d: %s", failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
@@ -969,10 +976,7 @@ singleipconnect(struct connectdata *conn,
Curl_closesocket(conn, sockfd); Curl_closesocket(conn, sockfd);
return CURLE_OK; return CURLE_OK;
} }
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); infof(data, " Trying %s...\n", ipaddress);
infof(data, " Trying %s...\n", conn->ip_addr_str);
Curl_persistconninfo(conn);
if(data->set.tcp_nodelay) if(data->set.tcp_nodelay)
tcpnodelay(conn, sockfd); tcpnodelay(conn, sockfd);
@@ -1033,7 +1037,7 @@ singleipconnect(struct connectdata *conn,
#endif #endif
if(-1 == rc) { if(-1 == rc) {
switch (error) { switch(error) {
case EINPROGRESS: case EINPROGRESS:
case EWOULDBLOCK: case EWOULDBLOCK:
#if defined(EAGAIN) #if defined(EAGAIN)
@@ -1045,25 +1049,25 @@ singleipconnect(struct connectdata *conn,
case EAGAIN: case EAGAIN:
#endif #endif
#endif #endif
*sockp = sockfd; res = CURLE_OK;
return CURLE_OK; break;
default: default:
/* unknown error, fallthrough and try another address! */ /* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect to %s: %s", infof(data, "Immediate connect fail for %s: %s\n",
conn->ip_addr_str, Curl_strerror(conn,error)); ipaddress, Curl_strerror(conn,error));
data->state.os_errno = error; data->state.os_errno = error;
/* connect failed */ /* connect failed */
Curl_closesocket(conn, sockfd); Curl_closesocket(conn, sockfd);
res = CURLE_COULDNT_CONNECT;
break;
} }
} }
else
if(!res)
*sockp = sockfd; *sockp = sockfd;
return CURLE_OK; return res;
} }
/* /*
@@ -1073,29 +1077,13 @@ singleipconnect(struct connectdata *conn,
*/ */
CURLcode Curl_connecthost(struct connectdata *conn, /* context */ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost, const struct Curl_dns_entry *remotehost)
curl_socket_t *sockconn, /* the connected socket */
Curl_addrinfo **addr, /* the one we used */
bool *connected) /* really connected? */
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
curl_socket_t sockfd = CURL_SOCKET_BAD;
Curl_addrinfo *ai;
Curl_addrinfo *curr_addr;
struct timeval after;
struct timeval before = Curl_tvnow(); struct timeval before = Curl_tvnow();
CURLcode res;
/************************************************************* long timeout_ms = Curl_timeleft(data, &before, TRUE);
* Figure out what maximum time we have left
*************************************************************/
long timeout_ms;
DEBUGASSERT(sockconn);
*connected = FALSE; /* default to not connected */
/* get the timeout left */
timeout_ms = Curl_timeleft(data, &before, TRUE);
if(timeout_ms < 0) { if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */ /* a precaution, no need to continue if time already is up */
@@ -1104,57 +1092,27 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
} }
conn->num_addr = Curl_num_addresses(remotehost->addr); conn->num_addr = Curl_num_addresses(remotehost->addr);
conn->tempaddr[0] = remotehost->addr;
conn->tempaddr[1] = NULL;
conn->tempsock[0] = CURL_SOCKET_BAD;
conn->tempsock[1] = CURL_SOCKET_BAD;
Curl_expire(conn->data,
HAPPY_EYEBALLS_TIMEOUT + (MULTI_TIMEOUT_INACCURACY/1000));
ai = remotehost->addr; /* Max time for the next connection attempt */
conn->timeoutms_per_addr =
conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
/* Below is the loop that attempts to connect to all IP-addresses we /* start connecting to first IP */
* know for the given host. One by one until one IP succeeds. res = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
*/ while(res != CURLE_OK &&
conn->tempaddr[0] &&
conn->tempaddr[0]->ai_next &&
conn->tempsock[0] == CURL_SOCKET_BAD)
res = trynextip(conn, FIRSTSOCKET, 0);
/* if(conn->tempsock[0] == CURL_SOCKET_BAD)
* Connecting with a Curl_addrinfo chain return res;
*/
for(curr_addr = ai; curr_addr; curr_addr = curr_addr->ai_next) {
CURLcode res;
/* Max time for the next address */
conn->timeoutms_per_addr = curr_addr->ai_next == NULL ?
timeout_ms : timeout_ms / 2;
/* start connecting to the IP curr_addr points to */
res = singleipconnect(conn, curr_addr,
&sockfd, connected);
if(res)
return res;
if(sockfd != CURL_SOCKET_BAD)
break;
/* get a new timeout for next attempt */
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);
if(timeout_ms < 0) {
failf(data, "connect() timed out!");
return CURLE_OPERATION_TIMEDOUT;
}
before = after;
} /* end of connect-to-each-address loop */
*sockconn = sockfd; /* the socket descriptor we've connected */
if(sockfd == CURL_SOCKET_BAD) {
/* no good connect was made */
failf(data, "couldn't connect to %s at %s:%ld",
conn->bits.proxy?"proxy":"host",
conn->bits.proxy?conn->proxy.name:conn->host.name, conn->port);
return CURLE_COULDNT_CONNECT;
}
/* leave the socket in non-blocking mode */
/* store the address we use */
if(addr)
*addr = curr_addr;
data->info.numconnects++; /* to track the number of connections made */ data->info.numconnects++; /* to track the number of connections made */

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -31,11 +31,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
bool *connected); bool *connected);
CURLcode Curl_connecthost(struct connectdata *conn, CURLcode Curl_connecthost(struct connectdata *conn,
const struct Curl_dns_entry *host, /* connect to const struct Curl_dns_entry *host);
this */
curl_socket_t *sockconn, /* not set if error */
Curl_addrinfo **addr, /* the one we used */
bool *connected); /* truly connected? */
/* generic function that returns how much time there's left to run, according /* generic function that returns how much time there's left to run, according
to the timeouts set */ to the timeouts set */
@@ -44,6 +40,8 @@ long Curl_timeleft(struct SessionHandle *data,
bool duringconnect); bool duringconnect);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
ipv4/ipv6 connection attempts */
/* /*
* Used to extract socket and connectdata struct for the most recent * Used to extract socket and connectdata struct for the most recent

View File

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

View File

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

View File

@@ -77,10 +77,6 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
ntlm = proxy ? &conn->proxyntlm : &conn->ntlm; ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
/* skip initial whitespaces */
while(*header && ISSPACE(*header))
header++;
if(checkprefix("NTLM", header)) { if(checkprefix("NTLM", header)) {
header += strlen("NTLM"); header += strlen("NTLM");

View File

@@ -356,7 +356,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
conn->response_header = NULL; conn->response_header = NULL;
break; break;
case NTLMSTATE_TYPE2: case NTLMSTATE_TYPE2:
input = aprintf("TT %s", conn->challenge_header); input = aprintf("TT %s\n", conn->challenge_header);
if(!input) if(!input)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
res = ntlm_wb_response(conn, input, ntlm->state); res = ntlm_wb_response(conn, input, ntlm->state);

View File

@@ -22,6 +22,8 @@
* RFC2831 DIGEST-MD5 authentication * RFC2831 DIGEST-MD5 authentication
* RFC4422 Simple Authentication and Security Layer (SASL) * RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication * RFC4616 PLAIN authentication
* RFC6749 OAuth 2.0 Authorization Framework
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -39,6 +41,10 @@
#include "warnless.h" #include "warnless.h"
#include "curl_memory.h" #include "curl_memory.h"
#ifdef USE_NSS
#include "nssg.h" /* for Curl_nss_force_init() */
#endif
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -49,7 +55,7 @@
/* Retrieves the value for a corresponding key from the challenge string /* Retrieves the value for a corresponding key from the challenge string
* returns TRUE if the key could be found, FALSE if it does not exists * returns TRUE if the key could be found, FALSE if it does not exists
*/ */
static bool sasl_digest_get_key_value(const unsigned char *chlg, static bool sasl_digest_get_key_value(const char *chlg,
const char *key, const char *key,
char *value, char *value,
size_t max_val_len, size_t max_val_len,
@@ -58,7 +64,7 @@ static bool sasl_digest_get_key_value(const unsigned char *chlg,
char *find_pos; char *find_pos;
size_t i; size_t i;
find_pos = strstr((const char *) chlg, key); find_pos = strstr(chlg, key);
if(!find_pos) if(!find_pos)
return FALSE; return FALSE;
@@ -94,18 +100,18 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
const char *passwdp, const char *passwdp,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH]; CURLcode result;
char *plainauth;
size_t ulen; size_t ulen;
size_t plen; size_t plen;
ulen = strlen(userp); ulen = strlen(userp);
plen = strlen(passwdp); plen = strlen(passwdp);
if(2 * ulen + plen + 2 > sizeof(plainauth)) { plainauth = malloc(2 * ulen + plen + 2);
if(!plainauth) {
*outlen = 0; *outlen = 0;
*outptr = NULL; *outptr = NULL;
/* Plainauth too small */
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@@ -117,8 +123,10 @@ CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
memcpy(plainauth + 2 * ulen + 2, passwdp, plen); memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
/* Base64 encode the reply */ /* Base64 encode the reply */
return Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
outlen); outlen);
Curl_safefree(plainauth);
return result;
} }
/* /*
@@ -160,7 +168,37 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
} }
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
/* /*
* Curl_sasl_decode_cram_md5_message()
*
* This is used to decode an already encoded CRAM-MD5 challenge message.
*
* Parameters:
*
* chlg64 [in] - Pointer to the base64 encoded challenge message.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
size_t *outlen)
{
CURLcode result = CURLE_OK;
size_t chlg64len = strlen(chlg64);
*outptr = NULL;
*outlen = 0;
/* Decode the challenge if necessary */
if(chlg64len && *chlg64 != '=')
result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);
return result;
}
/*
* Curl_sasl_create_cram_md5_message() * Curl_sasl_create_cram_md5_message()
* *
* This is used to generate an already encoded CRAM-MD5 response message ready * This is used to generate an already encoded CRAM-MD5 response message ready
@@ -169,7 +207,7 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
* Parameters: * Parameters:
* *
* data [in] - The session handle. * data [in] - The session handle.
* chlg64 [in] - Pointer to the base64 encoded challenge buffer. * chlg [in] - The challenge.
* userp [in] - The user name. * userp [in] - The user name.
* passdwp [in] - The user's password. * passdwp [in] - The user's password.
* outptr [in/out] - The address where a pointer to newly allocated memory * outptr [in/out] - The address where a pointer to newly allocated memory
@@ -179,55 +217,110 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
* Returns CURLE_OK on success. * Returns CURLE_OK on success.
*/ */
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
const char *chlg64, const char *chlg,
const char *userp, const char *userp,
const char *passwdp, const char *passwdp,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
size_t chlg64len = strlen(chlg64);
unsigned char *chlg = (unsigned char *) NULL;
size_t chlglen = 0; size_t chlglen = 0;
HMAC_context *ctxt; HMAC_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN]; unsigned char digest[MD5_DIGEST_LEN];
char response[MAX_CURL_USER_LENGTH + 2 * MD5_DIGEST_LEN + 1]; char *response;
/* Decode the challenge if necessary */ if(chlg)
if(chlg64len && *chlg64 != '=') { chlglen = strlen(chlg);
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
if(result)
return result;
}
/* Compute the digest using the password as the key */ /* Compute the digest using the password as the key */
ctxt = Curl_HMAC_init(Curl_HMAC_MD5, ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
(const unsigned char *) passwdp, (const unsigned char *) passwdp,
curlx_uztoui(strlen(passwdp))); curlx_uztoui(strlen(passwdp)));
if(!ctxt)
if(!ctxt) {
Curl_safefree(chlg);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
}
/* Update the digest with the given challenge */ /* Update the digest with the given challenge */
if(chlglen > 0) if(chlglen > 0)
Curl_HMAC_update(ctxt, chlg, curlx_uztoui(chlglen)); Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
curlx_uztoui(chlglen));
Curl_safefree(chlg);
/* Finalise the digest */ /* Finalise the digest */
Curl_HMAC_final(ctxt, digest); Curl_HMAC_final(ctxt, digest);
/* Prepare the response */ /* Generate the response */
snprintf(response, sizeof(response), response = aprintf(
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
userp, digest[0], digest[1], digest[2], digest[3], digest[4], userp, digest[0], digest[1], digest[2], digest[3], digest[4],
digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
digest[11], digest[12], digest[13], digest[14], digest[15]); digest[11], digest[12], digest[13], digest[14], digest[15]);
if(!response)
return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */ /* Base64 encode the response */
return Curl_base64_encode(data, response, 0, outptr, outlen); result = Curl_base64_encode(data, response, 0, outptr, outlen);
Curl_safefree(response);
return result;
}
/*
* Curl_sasl_decode_digest_md5_message()
*
* This is used to decode an already encoded DIGEST-MD5 challenge message.
*
* Parameters:
*
* chlg64 [in] - Pointer to the base64 encoded challenge message.
* nonce [in/out] - The buffer where the nonce will be stored.
* nlen [in] - The length of the nonce buffer.
* realm [in/out] - The buffer where the realm will be stored.
* rlen [in] - The length of the realm buffer.
* alg [in/out] - The buffer where the algorithm will be stored.
* alen [in] - The length of the algorithm buffer.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sasl_decode_digest_md5_message(const char *chlg64,
char *nonce, size_t nlen,
char *realm, size_t rlen,
char *alg, size_t alen)
{
CURLcode result = CURLE_OK;
unsigned char *chlg = NULL;
size_t chlglen = 0;
size_t chlg64len = strlen(chlg64);
if(chlg64len && *chlg64 != '=') {
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
if(result)
return result;
}
/* Ensure we have a valid challenge message */
if(!chlg)
return CURLE_BAD_CONTENT_ENCODING;
/* Retrieve nonce string from the challenge */
if(!sasl_digest_get_key_value((char *)chlg, "nonce=\"", nonce, nlen, '\"')) {
Curl_safefree(chlg);
return CURLE_BAD_CONTENT_ENCODING;
}
/* Retrieve realm string from the challenge */
if(!sasl_digest_get_key_value((char *)chlg, "realm=\"", realm, rlen, '\"')) {
/* Challenge does not have a realm, set empty string [RFC2831] page 6 */
strcpy(realm, "");
}
/* Retrieve algorithm string from the challenge */
if(!sasl_digest_get_key_value((char *)chlg, "algorithm=", alg, alen, ',')) {
Curl_safefree(chlg);
return CURLE_BAD_CONTENT_ENCODING;
}
Curl_safefree(chlg);
return CURLE_OK;
} }
/* /*
@@ -239,10 +332,11 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
* Parameters: * Parameters:
* *
* data [in] - The session handle. * data [in] - The session handle.
* chlg64 [in] - Pointer to the base64 encoded challenge buffer. * nonce [in] - The nonce.
* realm [in] - The realm.
* userp [in] - The user name. * userp [in] - The user name.
* passdwp [in] - The user's password. * passdwp [in] - The user's password.
* service [in] - The service type such as www, smtp or pop * service [in] - The service type such as www, smtp, pop or imap.
* outptr [in/out] - The address where a pointer to newly allocated memory * outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion. * holding the result will be stored upon completion.
* outlen [out] - The length of the output message. * outlen [out] - The length of the output message.
@@ -250,71 +344,36 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
* Returns CURLE_OK on success. * Returns CURLE_OK on success.
*/ */
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
const char *chlg64, const char *nonce,
const char *realm,
const char *userp, const char *userp,
const char *passwdp, const char *passwdp,
const char *service, const char *service,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
#ifndef DEBUGBUILD
static const char table16[] = "0123456789abcdef"; static const char table16[] = "0123456789abcdef";
#endif
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
unsigned char *chlg = (unsigned char *) NULL;
size_t chlglen = 0;
size_t i; size_t i;
MD5_context *ctxt; MD5_context *ctxt;
char *response = NULL;
unsigned char digest[MD5_DIGEST_LEN]; unsigned char digest[MD5_DIGEST_LEN];
char HA1_hex[2 * MD5_DIGEST_LEN + 1]; char HA1_hex[2 * MD5_DIGEST_LEN + 1];
char HA2_hex[2 * MD5_DIGEST_LEN + 1]; char HA2_hex[2 * MD5_DIGEST_LEN + 1];
char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; char resp_hash_hex[2 * MD5_DIGEST_LEN + 1];
char nonce[64];
char realm[128];
char alg[64];
char nonceCount[] = "00000001"; char nonceCount[] = "00000001";
char cnonce[] = "12345678"; /* will be changed */ char cnonce[] = "12345678"; /* will be changed */
char method[] = "AUTHENTICATE"; char method[] = "AUTHENTICATE";
char qop[] = "auth"; char qop[] = "auth";
char uri[128]; char uri[128];
char response[512];
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
if(result)
return result;
if(!chlg)
return CURLE_LOGIN_DENIED;
/* Retrieve nonce string from the challenge */
if(!sasl_digest_get_key_value(chlg, "nonce=\"", nonce,
sizeof(nonce), '\"')) {
Curl_safefree(chlg);
return CURLE_LOGIN_DENIED;
}
/* Retrieve realm string from the challenge */
if(!sasl_digest_get_key_value(chlg, "realm=\"", realm,
sizeof(realm), '\"')) {
/* Challenge does not have a realm, set empty string [RFC2831] page 6 */
strcpy(realm, "");
}
/* Retrieve algorithm string from the challenge */
if(!sasl_digest_get_key_value(chlg, "algorithm=", alg, sizeof(alg), ',')) {
Curl_safefree(chlg);
return CURLE_LOGIN_DENIED;
}
Curl_safefree(chlg);
/* We do not support other algorithms */
if(strcmp(alg, "md5-sess") != 0)
return CURLE_LOGIN_DENIED;
#ifndef DEBUGBUILD
/* Generate 64 bits of random data */ /* Generate 64 bits of random data */
for(i = 0; i < 8; i++) for(i = 0; i < 8; i++)
cnonce[i] = table16[Curl_rand(data)%16]; cnonce[i] = table16[Curl_rand(data)%16];
#endif
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
ctxt = Curl_MD5_init(Curl_DIGEST_MD5); ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
@@ -393,14 +452,20 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
for(i = 0; i < MD5_DIGEST_LEN; i++) for(i = 0; i < MD5_DIGEST_LEN; i++)
snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
snprintf(response, sizeof(response), /* Generate the response */
"username=\"%s\",realm=\"%s\",nonce=\"%s\"," response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
"cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s", "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s",
userp, realm, nonce, userp, realm, nonce,
cnonce, nonceCount, uri, resp_hash_hex); cnonce, nonceCount, uri, resp_hash_hex);
if(!response)
return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */ /* Base64 encode the response */
return Curl_base64_encode(data, response, 0, outptr, outlen); result = Curl_base64_encode(data, response, 0, outptr, outlen);
Curl_safefree(response);
return result;
} }
#endif #endif
@@ -430,8 +495,36 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
struct ntlmdata *ntlm, struct ntlmdata *ntlm,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, outlen);
outlen); }
/*
* Curl_sasl_decode_ntlm_type2_message()
*
* This is used to decode an already encoded NTLM type-2 message.
*
* Parameters:
*
* data [in] - Pointer to session handle.
* type2msg [in] - Pointer to the base64 encoded type-2 message.
* ntlm [in/out] - The ntlm data struct being used and modified.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
const char *type2msg,
struct ntlmdata *ntlm)
{
#ifdef USE_NSS
CURLcode result;
/* make sure the crypto backend is initialized */
result = Curl_nss_force_init(data);
if(result)
return result;
#endif
return Curl_ntlm_decode_type2_message(data, type2msg, ntlm);
} }
/* /*
@@ -443,7 +536,6 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
* Parameters: * Parameters:
* *
* data [in] - Pointer to session handle. * data [in] - Pointer to session handle.
* header [in] - Pointer to the base64 encoded type-2 message buffer.
* userp [in] - The user name in the format User or Domain\User. * userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password. * passdwp [in] - The user's password.
* ntlm [in/out] - The ntlm data struct being used and modified. * ntlm [in/out] - The ntlm data struct being used and modified.
@@ -454,21 +546,53 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
* Returns CURLE_OK on success. * Returns CURLE_OK on success.
*/ */
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
const char *header,
const char *userp, const char *userp,
const char *passwdp, const char *passwdp,
struct ntlmdata *ntlm, struct ntlmdata *ntlm,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
CURLcode result = Curl_ntlm_decode_type2_message(data, header, ntlm); return Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm, outptr,
outlen);
}
#endif /* USE_NTLM */
if(!result) /*
result = Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm, * Curl_sasl_create_xoauth2_message()
outptr, outlen); *
* This is used to generate an already encoded OAuth 2.0 message ready for
* sending to the recipient.
*
* Parameters:
*
* data [in] - The session handle.
* user [in] - The user name.
* bearer [in] - The bearer token.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
* outlen [out] - The length of the output message.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
const char *user,
const char *bearer,
char **outptr, size_t *outlen)
{
CURLcode result = CURLE_OK;
char *xoauth = NULL;
/* Generate the message */
xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
if(!xoauth)
return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */
result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
Curl_safefree(xoauth);
return result; return result;
} }
#endif /* USE_NTLM */
/* /*
* Curl_sasl_cleanup() * Curl_sasl_cleanup()

View File

@@ -24,18 +24,34 @@
#include "pingpong.h" #include "pingpong.h"
/* Authentication mechanism flags */
#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 */ /* Authentication mechanism values */
#define SASL_AUTH_NONE 0 #define SASL_AUTH_NONE 0
#define SASL_AUTH_ANY ~0 #define SASL_AUTH_ANY ~0U
/* Authentication mechanism flags */
#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)
#define SASL_MECH_XOAUTH2 (1 << 7)
/* Authentication mechanism strings */
#define SASL_MECH_STRING_LOGIN "LOGIN"
#define SASL_MECH_STRING_PLAIN "PLAIN"
#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5"
#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5"
#define SASL_MECH_STRING_GSSAPI "GSSAPI"
#define SASL_MECH_STRING_EXTERNAL "EXTERNAL"
#define SASL_MECH_STRING_NTLM "NTLM"
#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2"
/* This is used to test whether the line starts with the given mechanism */
#define sasl_mech_equal(line, wordlen, mech) \
(wordlen == (sizeof(mech) - 1) / sizeof(char) && \
!memcmp(line, mech, wordlen))
/* This is used to generate a base64 encoded PLAIN authentication message */ /* This is used to generate a base64 encoded PLAIN authentication message */
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data, CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
@@ -50,16 +66,27 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
size_t *outlen); size_t *outlen);
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
/* This is used to decode a base64 encoded CRAM-MD5 challange message */
CURLcode Curl_sasl_decode_cram_md5_message(const char *chlg64, char **outptr,
size_t *outlen);
/* This is used to generate a base64 encoded CRAM-MD5 response message */ /* This is used to generate a base64 encoded CRAM-MD5 response message */
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data, CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
const char *chlg64, const char *chlg,
const char *user, const char *user,
const char *passwdp, const char *passwdp,
char **outptr, size_t *outlen); char **outptr, size_t *outlen);
/* This is used to decode a base64 encoded DIGEST-MD5 challange message */
CURLcode Curl_sasl_decode_digest_md5_message(const char *chlg64,
char *nonce, size_t nlen,
char *realm, size_t rlen,
char *alg, size_t alen);
/* This is used to generate a base64 encoded DIGEST-MD5 response message */ /* This is used to generate a base64 encoded DIGEST-MD5 response message */
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
const char *chlg64, const char *nonce,
const char *realm,
const char *user, const char *user,
const char *passwdp, const char *passwdp,
const char *service, const char *service,
@@ -74,10 +101,13 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
char **outptr, char **outptr,
size_t *outlen); size_t *outlen);
/* This is used to decode an incoming NTLM type-2 message and generate a /* This is used to decode a base64 encoded NTLM type-2 message */
base64 encoded type-3 response */ CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
const char *type2msg,
struct ntlmdata *ntlm);
/* This is used to generate a base64 encoded NTLM type-3 message */
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
const char *header,
const char *userp, const char *userp,
const char *passwdp, const char *passwdp,
struct ntlmdata *ntlm, struct ntlmdata *ntlm,
@@ -85,6 +115,13 @@ CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
#endif /* USE_NTLM */ #endif /* USE_NTLM */
/* This is used to generate a base64 encoded XOAUTH2 authentication message
containing the user name and bearer token */
CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
const char *user,
const char *bearer,
char **outptr, size_t *outlen);
/* This is used to cleanup any libraries or curl modules used by the sasl /* This is used to cleanup any libraries or curl modules used by the sasl
functions */ functions */
void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused);

View File

@@ -180,6 +180,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_1_CLIENT |
SP_PROT_TLS1_2_CLIENT; SP_PROT_TLS1_2_CLIENT;
break; break;
case CURL_SSLVERSION_TLSv1_0:
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_1:
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT;
break;
case CURL_SSLVERSION_TLSv1_2:
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
break;
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
break; break;

View File

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

View File

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

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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -98,8 +98,19 @@ cyassl_connect_step1(struct connectdata *conn,
req_method = SSLv23_client_method(); req_method = SSLv23_client_method();
break; break;
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
infof(data, "CyaSSL cannot be configured to use TLS 1.0-1.2, "
"TLS 1.0 is used exclusively\n");
req_method = TLSv1_client_method(); req_method = TLSv1_client_method();
break; break;
case CURL_SSLVERSION_TLSv1_0:
req_method = TLSv1_client_method();
break;
case CURL_SSLVERSION_TLSv1_1:
req_method = TLSv1_1_client_method();
break;
case CURL_SSLVERSION_TLSv1_2:
req_method = TLSv1_2_client_method();
break;
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
req_method = SSLv3_client_method(); req_method = SSLv3_client_method();
break; break;

View File

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

View File

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

View File

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

485
lib/ftp.c
View File

@@ -59,11 +59,7 @@
#include "ftp.h" #include "ftp.h"
#include "fileinfo.h" #include "fileinfo.h"
#include "ftplistparser.h" #include "ftplistparser.h"
#include "curl_sec.h"
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#include "krb4.h"
#endif
#include "strtoofft.h" #include "strtoofft.h"
#include "strequal.h" #include "strequal.h"
#include "sslgen.h" #include "sslgen.h"
@@ -225,7 +221,7 @@ const struct Curl_handler Curl_handler_ftps = {
static const struct Curl_handler Curl_handler_ftp_proxy = { static const struct Curl_handler Curl_handler_ftp_proxy = {
"FTP", /* scheme */ "FTP", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -251,7 +247,7 @@ static const struct Curl_handler Curl_handler_ftp_proxy = {
static const struct Curl_handler Curl_handler_ftps_proxy = { static const struct Curl_handler Curl_handler_ftps_proxy = {
"FTPS", /* scheme */ "FTPS", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -493,7 +489,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
static CURLcode InitiateTransfer(struct connectdata *conn) static CURLcode InitiateTransfer(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if(conn->ssl[SECONDARYSOCKET].use) { if(conn->ssl[SECONDARYSOCKET].use) {
@@ -615,7 +611,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
{ {
struct connectdata *conn = pp->conn; struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #ifdef HAVE_GSSAPI
char * const buf = data->state.buffer; char * const buf = data->state.buffer;
#endif #endif
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@@ -623,7 +619,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
result = Curl_pp_readresp(sockfd, pp, &code, size); result = Curl_pp_readresp(sockfd, pp, &code, size);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #if defined(HAVE_GSSAPI)
/* handle the security-oriented responses 6xx ***/ /* handle the security-oriented responses 6xx ***/
/* FIXME: some errorchecking perhaps... ***/ /* FIXME: some errorchecking perhaps... ***/
switch(code) { switch(code) {
@@ -775,6 +771,47 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
return result; return result;
} }
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const ftp_state_names[]={
"STOP",
"WAIT220",
"AUTH",
"USER",
"PASS",
"ACCT",
"PBSZ",
"PROT",
"CCC",
"PWD",
"SYST",
"NAMEFMT",
"QUOTE",
"RETR_PREQUOTE",
"STOR_PREQUOTE",
"POSTQUOTE",
"CWD",
"MKD",
"MDTM",
"TYPE",
"LIST_TYPE",
"RETR_TYPE",
"STOR_TYPE",
"SIZE",
"RETR_SIZE",
"STOR_SIZE",
"REST",
"RETR_REST",
"PORT",
"PRET",
"PASV",
"LIST",
"RETR",
"STOR",
"QUIT"
};
#endif
/* This is the ONLY way to change FTP state! */ /* This is the ONLY way to change FTP state! */
static void _state(struct connectdata *conn, static void _state(struct connectdata *conn,
ftpstate newstate ftpstate newstate
@@ -783,51 +820,12 @@ static void _state(struct connectdata *conn,
#endif #endif
) )
{ {
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
"STOP",
"WAIT220",
"AUTH",
"USER",
"PASS",
"ACCT",
"PBSZ",
"PROT",
"CCC",
"PWD",
"SYST",
"NAMEFMT",
"QUOTE",
"RETR_PREQUOTE",
"STOR_PREQUOTE",
"POSTQUOTE",
"CWD",
"MKD",
"MDTM",
"TYPE",
"LIST_TYPE",
"RETR_TYPE",
"STOR_TYPE",
"SIZE",
"RETR_SIZE",
"STOR_SIZE",
"REST",
"RETR_REST",
"PORT",
"PRET",
"PASV",
"LIST",
"RETR",
"STOR",
"QUIT"
};
#endif
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(ftpc->state != newstate) if(ftpc->state != newstate)
infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
(void *)ftpc, lineno, names[ftpc->state], names[newstate]); (void *)ftpc, lineno, ftp_state_names[ftpc->state],
ftp_state_names[newstate]);
#endif #endif
ftpc->state = newstate; ftpc->state = newstate;
} }
@@ -835,7 +833,7 @@ static void _state(struct connectdata *conn,
static CURLcode ftp_state_user(struct connectdata *conn) static CURLcode ftp_state_user(struct connectdata *conn)
{ {
CURLcode result; CURLcode result;
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
/* send USER */ /* send USER */
PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
@@ -874,31 +872,21 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
return GETSOCK_BLANK; return GETSOCK_BLANK;
/* When in DO_MORE state, we could be either waiting for us to connect to a /* When in DO_MORE state, we could be either waiting for us to connect to a
remote site, or we could wait for that site to connect to us. Or just * remote site, or we could wait for that site to connect to us. Or just
handle ordinary commands. * handle ordinary commands.
*/
When waiting for a connect, we can be in FTP_STOP state (or we're in if(FTP_STOP == ftpc->state) {
FTP_STOR when we do an upload) and then we wait for the secondary socket /* if stopped and still in this state, then we're also waiting for a
to become writeable. . If we're in another state, we're still handling connect on the secondary connection */
commands on the control (primary) connection. socks[0] = conn->sock[FIRSTSOCKET];
socks[1] = conn->sock[SECONDARYSOCKET];
*/ return GETSOCK_READSOCK(FIRSTSOCKET) |
GETSOCK_WRITESOCK(SECONDARYSOCKET);
switch(ftpc->state) { }
case FTP_STOP: else
case FTP_STOR:
break;
default:
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
}
socks[0] = conn->sock[SECONDARYSOCKET];
if(ftpc->wait_data_conn) {
socks[1] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0) | GETSOCK_READSOCK(1);
}
return GETSOCK_READSOCK(0);
} }
/* This is called after the FTP_QUOTE state is passed. /* This is called after the FTP_QUOTE state is passed.
@@ -1382,7 +1370,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
if(ftp->transfer != FTPTRANSFER_BODY) { if(ftp->transfer != FTPTRANSFER_BODY) {
@@ -1425,7 +1413,7 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
static CURLcode ftp_state_rest(struct connectdata *conn) static CURLcode ftp_state_rest(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
@@ -1446,7 +1434,7 @@ static CURLcode ftp_state_rest(struct connectdata *conn)
static CURLcode ftp_state_size(struct connectdata *conn) static CURLcode ftp_state_size(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
@@ -1557,7 +1545,7 @@ static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
static CURLcode ftp_state_type(struct connectdata *conn) static CURLcode ftp_state_type(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -1614,7 +1602,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
bool sizechecked) bool sizechecked)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
int seekerr = CURL_SEEKFUNC_OK; int seekerr = CURL_SEEKFUNC_OK;
@@ -1712,7 +1700,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
bool quote=FALSE; bool quote=FALSE;
struct curl_slist *item; struct curl_slist *item;
@@ -1814,23 +1802,87 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
return result; return result;
} }
/*
* Perform the necessary magic that needs to be done once the TCP connection
* to the proxy has completed.
*/
static CURLcode proxy_magic(struct connectdata *conn,
char *newhost, unsigned short newport,
bool *magicdone)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
*magicdone = FALSE;
switch(conn->proxytype) {
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
newport, SECONDARYSOCKET, conn);
*magicdone = TRUE;
break;
case CURLPROXY_SOCKS4:
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
SECONDARYSOCKET, conn, FALSE);
*magicdone = TRUE;
break;
case CURLPROXY_SOCKS4A:
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
SECONDARYSOCKET, conn, TRUE);
*magicdone = TRUE;
break;
case CURLPROXY_HTTP:
case CURLPROXY_HTTP_1_0:
/* do nothing here. handled later. */
break;
default:
failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
break;
}
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* BLOCKING */
/* We want "seamless" FTP operations through HTTP proxy tunnel */
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
* member conn->proto.http; we want FTP through HTTP and we have to
* change the member temporarily for connecting to the HTTP proxy. After
* Curl_proxyCONNECT we have to set back the member to the original
* struct FTP pointer
*/
struct HTTP http_proxy;
struct FTP *ftp_save = data->req.protop;
memset(&http_proxy, 0, sizeof(http_proxy));
data->req.protop = &http_proxy;
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
data->req.protop = ftp_save;
if(result)
return result;
if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
/* the CONNECT procedure is not complete, the tunnel is not yet up */
state(conn, FTP_STOP); /* this phase is completed */
return result;
}
else
*magicdone = TRUE;
}
return result;
}
static CURLcode ftp_state_pasv_resp(struct connectdata *conn, static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
int ftpcode) int ftpcode)
{ {
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result; CURLcode result;
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
Curl_addrinfo *conninfo;
struct Curl_dns_entry *addr=NULL; struct Curl_dns_entry *addr=NULL;
int rc; int rc;
unsigned short connectport; /* the local port connect() should use! */ unsigned short connectport; /* the local port connect() should use! */
unsigned short newport=0; /* remote port */
bool connected;
/* newhost must be able to hold a full IP-style address in ASCII, which
in the IPv6 case means 5*8-1 = 39 letters */
#define NEWHOST_BUFSIZE 48
char newhost[NEWHOST_BUFSIZE];
char *str=&data->state.buffer[4]; /* start on the first letter */ char *str=&data->state.buffer[4]; /* start on the first letter */
if((ftpc->count1 == 0) && if((ftpc->count1 == 0) &&
@@ -1863,7 +1915,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_PASV_REPLY; return CURLE_FTP_WEIRD_PASV_REPLY;
} }
if(ptr) { if(ptr) {
newport = (unsigned short)(num & 0xffff); ftpc->newport = (unsigned short)(num & 0xffff);
if(conn->bits.tunnel_proxy || if(conn->bits.tunnel_proxy ||
conn->proxytype == CURLPROXY_SOCKS5 || conn->proxytype == CURLPROXY_SOCKS5 ||
@@ -1872,10 +1924,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
conn->proxytype == CURLPROXY_SOCKS4A) conn->proxytype == CURLPROXY_SOCKS4A)
/* proxy tunnel -> use other host info because ip_addr_str is the /* proxy tunnel -> use other host info because ip_addr_str is the
proxy address not the ftp host */ proxy address not the ftp host */
snprintf(newhost, sizeof(newhost), "%s", conn->host.name); snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
conn->host.name);
else else
/* use the same IP we are already connected to */ /* use the same IP we are already connected to */
snprintf(newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str); snprintf(ftpc->newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str);
} }
} }
else else
@@ -1928,14 +1981,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
conn->proxytype == CURLPROXY_SOCKS4A) conn->proxytype == CURLPROXY_SOCKS4A)
/* proxy tunnel -> use other host info because ip_addr_str is the /* proxy tunnel -> use other host info because ip_addr_str is the
proxy address not the ftp host */ proxy address not the ftp host */
snprintf(newhost, sizeof(newhost), "%s", conn->host.name); snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", conn->host.name);
else else
snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str); snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
conn->ip_addr_str);
} }
else else
snprintf(newhost, sizeof(newhost), snprintf(ftpc->newhost, sizeof(ftpc->newhost),
"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
} }
else if(ftpc->count1 == 0) { else if(ftpc->count1 == 0) {
/* EPSV failed, move on to PASV */ /* EPSV failed, move on to PASV */
@@ -1969,24 +2023,21 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
} }
else { else {
/* normal, direct, ftp connection */ /* normal, direct, ftp connection */
rc = Curl_resolv(conn, newhost, newport, &addr); rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)
/* BLOCKING */ /* BLOCKING */
(void)Curl_resolver_wait_resolv(conn, &addr); (void)Curl_resolver_wait_resolv(conn, &addr);
connectport = newport; /* we connect to the remote port */ connectport = ftpc->newport; /* we connect to the remote port */
if(!addr) { if(!addr) {
failf(data, "Can't resolve new host %s:%hu", newhost, connectport); failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
return CURLE_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST;
} }
} }
result = Curl_connecthost(conn, conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
addr, result = Curl_connecthost(conn, addr);
&conn->sock[SECONDARYSOCKET],
&conninfo,
&connected);
Curl_resolv_unlock(data, addr); /* we're done using this address */ Curl_resolv_unlock(data, addr); /* we're done using this address */
@@ -1997,88 +2048,17 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return result; return result;
} }
conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
/* /*
* When this is used from the multi interface, this might've returned with * When this is used from the multi interface, this might've returned with
* the 'connected' set to FALSE and thus we are now awaiting a non-blocking * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
* connect to connect and we should not be "hanging" here waiting. * connect to connect.
*/ */
if(data->set.verbose) if(data->set.verbose)
/* this just dumps information about this second connection */ /* this just dumps information about this second connection */
ftp_pasv_verbose(conn, conninfo, newhost, connectport); ftp_pasv_verbose(conn, conn->ip_addr, ftpc->newhost, connectport);
switch(conn->proxytype) {
/* FIX: this MUST wait for a proper connect first if 'connected' is
* FALSE */
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport,
SECONDARYSOCKET, conn);
connected = TRUE;
break;
case CURLPROXY_SOCKS4:
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
SECONDARYSOCKET, conn, FALSE);
connected = TRUE;
break;
case CURLPROXY_SOCKS4A:
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
SECONDARYSOCKET, conn, TRUE);
connected = TRUE;
break;
case CURLPROXY_HTTP:
case CURLPROXY_HTTP_1_0:
/* do nothing here. handled later. */
break;
default:
failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
break;
}
if(result) {
if(ftpc->count1 == 0 && ftpcode == 229)
return ftp_epsv_disable(conn);
return result;
}
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* FIX: this MUST wait for a proper connect first if 'connected' is
* FALSE */
/* BLOCKING */
/* We want "seamless" FTP operations through HTTP proxy tunnel */
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member
* conn->proto.http; we want FTP through HTTP and we have to change the
* member temporarily for connecting to the HTTP proxy. After
* Curl_proxyCONNECT we have to set back the member to the original struct
* FTP pointer
*/
struct HTTP http_proxy;
struct FTP *ftp_save = data->state.proto.ftp;
memset(&http_proxy, 0, sizeof(http_proxy));
data->state.proto.http = &http_proxy;
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport);
data->state.proto.ftp = ftp_save;
if(result)
return result;
if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
/* the CONNECT procedure is not complete, the tunnel is not yet up */
state(conn, FTP_STOP); /* this phase is completed */
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
return result;
}
}
conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
conn->bits.do_more = TRUE; conn->bits.do_more = TRUE;
state(conn, FTP_STOP); /* this phase is completed */ state(conn, FTP_STOP); /* this phase is completed */
@@ -2124,7 +2104,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
switch(ftpcode) { switch(ftpcode) {
@@ -2258,7 +2238,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data; struct SessionHandle *data=conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
if(data->set.max_filesize && (filesize > data->set.max_filesize)) { if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
@@ -2427,6 +2407,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
if(data->set.ftp_use_port) { if(data->set.ftp_use_port) {
bool connected; bool connected;
state(conn, FTP_STOP); /* no longer in STOR state */
result = AllowServerConnect(conn, &connected); result = AllowServerConnect(conn, &connected);
if(result) if(result)
return result; return result;
@@ -2450,7 +2432,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
char *buf = data->state.buffer; char *buf = data->state.buffer;
if((ftpcode == 150) || (ftpcode == 125)) { if((ftpcode == 150) || (ftpcode == 125)) {
@@ -2574,19 +2556,6 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
#ifdef HAVE_KRB4
if(conn->data->set.krb) {
/* We may need to issue a KAUTH here to have access to the files
* do it if user supplied a password
*/
if(conn->passwd && *conn->passwd) {
/* BLOCKING */
result = Curl_krb_kauth(conn);
if(result)
return result;
}
}
#endif
if(conn->ssl[FIRSTSOCKET].use) { if(conn->ssl[FIRSTSOCKET].use) {
/* PBSZ = PROTECTION BUFFER SIZE. /* PBSZ = PROTECTION BUFFER SIZE.
@@ -2618,7 +2587,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -2716,7 +2685,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
} }
/* We have received a 220 response fine, now we proceed. */ /* We have received a 220 response fine, now we proceed. */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #ifdef HAVE_GSSAPI
if(data->set.krb) { if(data->set.krb) {
/* If not anonymous login, try a secure login. Note that this /* If not anonymous login, try a secure login. Note that this
procedure is still BLOCKING. */ procedure is still BLOCKING. */
@@ -3158,56 +3127,6 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
return result; return result;
} }
/*
* Allocate and initialize the struct FTP for the current SessionHandle. If
* need be.
*/
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
/* workaround icc 9.1 optimizer issue */
#pragma optimize("", off)
#endif
static CURLcode ftp_init(struct connectdata *conn)
{
struct FTP *ftp;
if(NULL == conn->data->state.proto.ftp) {
conn->data->state.proto.ftp = malloc(sizeof(struct FTP));
if(NULL == conn->data->state.proto.ftp)
return CURLE_OUT_OF_MEMORY;
}
ftp = conn->data->state.proto.ftp;
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->data->req.bytecount;
ftp->transfer = FTPTRANSFER_BODY;
ftp->downloadsize = 0;
/* No need to duplicate user+password, the connectdata struct won't change
during a session, but we re-init them here since on subsequent inits
since the conn struct may have changed or been replaced.
*/
ftp->user = conn->user;
ftp->passwd = conn->passwd;
if(isBadFtpString(ftp->user))
return CURLE_URL_MALFORMAT;
if(isBadFtpString(ftp->passwd))
return CURLE_URL_MALFORMAT;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
return CURLE_OK;
}
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
/* workaround icc 9.1 optimizer issue */
#pragma optimize("", on)
#endif
/* /*
* ftp_connect() should do everything that is to be considered a part of * ftp_connect() should do everything that is to be considered a part of
* the connection phase. * the connection phase.
@@ -3225,14 +3144,6 @@ static CURLcode ftp_connect(struct connectdata *conn,
*done = FALSE; /* default to not done yet */ *done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
result = ftp_init(conn);
if(CURLE_OK != result)
return result;
/* We always support persistent connections on ftp */ /* We always support persistent connections on ftp */
conn->bits.close = FALSE; conn->bits.close = FALSE;
@@ -3272,7 +3183,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
bool premature) bool premature)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp; struct pingpong *pp = &ftpc->pp;
ssize_t nread; ssize_t nread;
@@ -3689,7 +3600,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
bool complete = FALSE; bool complete = FALSE;
/* the ftp struct is inited in ftp_connect() */ /* the ftp struct is inited in ftp_connect() */
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
/* if the second connection isn't done yet, wait for it */ /* if the second connection isn't done yet, wait for it */
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
@@ -3706,6 +3617,10 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* Ready to do more? */ /* Ready to do more? */
if(connected) { if(connected) {
DEBUGF(infof(data, "DO-MORE connected phase starts\n")); DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
if(conn->bits.proxy) {
infof(data, "Connection to proxy confirmed\n");
result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
}
} }
else { else {
if(result && (ftpc->count1 == 0)) { if(result && (ftpc->count1 == 0)) {
@@ -3837,7 +3752,7 @@ CURLcode ftp_perform(struct connectdata *conn,
if(conn->data->set.opt_no_body) { if(conn->data->set.opt_no_body) {
/* requested no body means no transfer... */ /* requested no body means no transfer... */
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
ftp->transfer = FTPTRANSFER_INFO; ftp->transfer = FTPTRANSFER_INFO;
} }
@@ -4099,17 +4014,6 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
ftpc->wait_data_conn = FALSE; /* default to no such wait */ ftpc->wait_data_conn = FALSE; /* default to no such wait */
/*
Since connections can be re-used between SessionHandles, this might be a
connection already existing but on a fresh SessionHandle struct so we must
make sure we have a good 'struct FTP' to play with. For new connections,
the struct FTP is allocated and setup in the ftp_connect() function.
*/
Curl_reset_reqproto(conn);
retcode = ftp_init(conn);
if(retcode)
return retcode;
if(conn->data->set.wildcardmatch) { if(conn->data->set.wildcardmatch) {
retcode = wc_statemach(conn); retcode = wc_statemach(conn);
if(conn->data->wildcard.state == CURLWC_SKIP || if(conn->data->wildcard.state == CURLWC_SKIP ||
@@ -4141,7 +4045,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
size_t write_len; size_t write_len;
char *sptr=s; char *sptr=s;
CURLcode res = CURLE_OK; CURLcode res = CURLE_OK;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #ifdef HAVE_GSSAPI
enum protection_level data_sec = conn->data_prot; enum protection_level data_sec = conn->data_prot;
#endif #endif
@@ -4161,12 +4065,12 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
return(res); return(res);
for(;;) { for(;;) {
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD; conn->data_prot = PROT_CMD;
#endif #endif
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
&bytes_written); &bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #ifdef HAVE_GSSAPI
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
conn->data_prot = data_sec; conn->data_prot = data_sec;
#endif #endif
@@ -4268,7 +4172,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
Curl_pp_disconnect(pp); Curl_pp_disconnect(pp);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI) #ifdef HAVE_GSSAPI
Curl_sec_end(conn); Curl_sec_end(conn);
#endif #endif
@@ -4287,7 +4191,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->state.proto.ftp; struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
const char *slash_pos; /* position of the first '/' char in curpos */ const char *slash_pos; /* position of the first '/' char in curpos */
const char *path_to_use = data->state.path; const char *path_to_use = data->state.path;
@@ -4342,7 +4246,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
dirlen++; dirlen++;
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/", ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? curlx_sztosi(dirlen) : 1, slash_pos ? curlx_uztosi(dirlen) : 1,
NULL); NULL);
if(!ftpc->dirs[0]) { if(!ftpc->dirs[0]) {
freedirs(ftpc); freedirs(ftpc);
@@ -4477,7 +4381,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
static CURLcode ftp_dophase_done(struct connectdata *conn, static CURLcode ftp_dophase_done(struct connectdata *conn,
bool connected) bool connected)
{ {
struct FTP *ftp = conn->data->state.proto.ftp; struct FTP *ftp = conn->data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc; struct ftp_conn *ftpc = &conn->proto.ftpc;
if(connected) { if(connected) {
@@ -4572,11 +4476,12 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
return result; return result;
} }
static CURLcode ftp_setup_connection(struct connectdata * conn) static CURLcode ftp_setup_connection(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char * type; char *type;
char command; char command;
struct FTP *ftp;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel ftp operations through the proxy, we /* Unless we have asked to tunnel ftp operations through the proxy, we
@@ -4592,18 +4497,18 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
return CURLE_UNSUPPORTED_PROTOCOL; return CURLE_UNSUPPORTED_PROTOCOL;
#endif #endif
} }
/* /* set it up as a HTTP connection instead */
* We explicitly mark this connection as persistent here as we're doing return conn->handler->setup_connection(conn);
* FTP over HTTP and thus we accidentally avoid setting this value
* otherwise.
*/
conn->bits.close = FALSE;
#else #else
failf(data, "FTP over http proxy requires HTTP support built-in!"); failf(data, "FTP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL; return CURLE_UNSUPPORTED_PROTOCOL;
#endif #endif
} }
conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
if(NULL == ftp)
return CURLE_OUT_OF_MEMORY;
data->state.path++; /* don't include the initial slash */ data->state.path++; /* don't include the initial slash */
data->state.slash_removed = TRUE; /* we've skipped the slash */ data->state.slash_removed = TRUE; /* we've skipped the slash */
@@ -4636,6 +4541,24 @@ static CURLcode ftp_setup_connection(struct connectdata * conn)
} }
} }
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->data->req.bytecount;
ftp->transfer = FTPTRANSFER_BODY;
ftp->downloadsize = 0;
/* No need to duplicate user+password, the connectdata struct won't change
during a session, but we re-init them here since on subsequent inits
since the conn struct may have changed or been replaced.
*/
ftp->user = conn->user;
ftp->passwd = conn->passwd;
if(isBadFtpString(ftp->user))
return CURLE_URL_MALFORMAT;
if(isBadFtpString(ftp->passwd))
return CURLE_URL_MALFORMAT;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
return CURLE_OK; return CURLE_OK;
} }

View File

@@ -147,6 +147,12 @@ struct ftp_conn {
curl_off_t known_filesize; /* file size is different from -1, if wildcard curl_off_t known_filesize; /* file size is different from -1, if wildcard
LIST parsing was done and wc_statemach set LIST parsing was done and wc_statemach set
it */ it */
/* newhost must be able to hold a full IP-style address in ASCII, which
in the IPv6 case means 5*8-1 = 39 letters */
#define NEWHOST_BUFSIZE 48
char newhost[NEWHOST_BUFSIZE]; /* this is the pair to connect the DATA... */
unsigned short newport; /* connection to */
}; };
#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ #define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */

View File

@@ -277,7 +277,57 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
ptr.to_certinfo = &data->info.certs; ptr.to_certinfo = &data->info.certs;
*param_slistp = ptr.to_slist; *param_slistp = ptr.to_slist;
break; break;
case CURLINFO_TLS_SESSION:
{
struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
param_slistp;
struct curl_tlssessioninfo *tsi = &data->tsi;
struct connectdata *conn = data->easy_conn;
unsigned int sockindex = 0;
*tsip = tsi;
tsi->backend = CURLSSLBACKEND_NONE;
tsi->internals = NULL;
if(!conn)
break;
/* Find the active ("in use") SSL connection, if any */
while((sockindex < sizeof(conn->ssl) / sizeof(conn->ssl[0])) &&
(!conn->ssl[sockindex].use))
sockindex++;
if(sockindex == sizeof(conn->ssl) / sizeof(conn->ssl[0]))
break; /* no SSL session found */
/* Return the TLS session information from the relevant backend */
#ifdef USE_SSLEAY
tsi->backend = CURLSSLBACKEND_OPENSSL;
tsi->internals = conn->ssl[sockindex].ctx;
#endif
#ifdef USE_GNUTLS
tsi->backend = CURLSSLBACKEND_GNUTLS;
tsi->internals = conn->ssl[sockindex].session;
#endif
#ifdef USE_NSS
tsi->backend = CURLSSLBACKEND_NSS;
tsi->internals = conn->ssl[sockindex].handle;
#endif
#ifdef USE_QSOSSL
tsi->backend = CURLSSLBACKEND_QSOSSL;
tsi->internals = conn->ssl[sockindex].handle;
#endif
#ifdef USE_GSKIT
tsi->backend = CURLSSLBACKEND_GSKIT;
tsi->internals = conn->ssl[sockindex].handle;
#endif
/* NOTE: For other SSL backends, it is not immediately clear what data
to return from 'struct ssl_connect_data'; thus, for now we keep the
backend as CURLSSLBACKEND_NONE in those cases, which should be
interpreted as "not supported" */
break;
}
break;
default: default:
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }

View File

@@ -29,9 +29,38 @@
/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */ /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 #define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
#endif #endif
#ifndef GSK_TLSV10_CIPHER_SPECS
#define GSK_TLSV10_CIPHER_SPECS 236
#endif
#ifndef GSK_TLSV11_CIPHER_SPECS
#define GSK_TLSV11_CIPHER_SPECS 237
#endif
#ifndef GSK_TLSV12_CIPHER_SPECS
#define GSK_TLSV12_CIPHER_SPECS 238
#endif
#ifndef GSK_PROTOCOL_TLSV11
#define GSK_PROTOCOL_TLSV11 437
#endif
#ifndef GSK_PROTOCOL_TLSV12
#define GSK_PROTOCOL_TLSV12 438
#endif
#ifndef GSK_FALSE
#define GSK_FALSE 0
#endif
#ifndef GSK_TRUE
#define GSK_TRUE 1
#endif
#ifdef HAVE_LIMITS_H #ifdef HAVE_LIMITS_H
# include <limits.h> # include <limits.h>
#endif #endif
@@ -54,30 +83,65 @@
#include "memdebug.h" #include "memdebug.h"
/* SSL version flags. */
#define CURL_GSKPROTO_SSLV2 0
#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
#define CURL_GSKPROTO_SSLV3 1
#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
#define CURL_GSKPROTO_TLSV10 2
#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
#define CURL_GSKPROTO_TLSV11 3
#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
#define CURL_GSKPROTO_TLSV12 4
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5
/* Supported ciphers. */ /* Supported ciphers. */
typedef struct { typedef struct {
const char * name; /* Cipher name. */ const char *name; /* Cipher name. */
const char * gsktoken; /* Corresponding token for GSKit String. */ const char *gsktoken; /* Corresponding token for GSKit String. */
int sslver; /* SSL version. */ unsigned int versions; /* SSL version flags. */
} gskit_cipher; } gskit_cipher;
static const gskit_cipher ciphertable[] = { static const gskit_cipher ciphertable[] = {
{ "null-md5", "01", CURL_SSLVERSION_SSLv3 }, { "null-md5", "01",
{ "null-sha", "02", CURL_SSLVERSION_SSLv3 }, CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
{ "exp-rc4-md5", "03", CURL_SSLVERSION_SSLv3 }, CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
{ "rc4-md5", "04", CURL_SSLVERSION_SSLv3 }, { "null-sha", "02",
{ "rc4-sha", "05", CURL_SSLVERSION_SSLv3 }, CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
{ "exp-rc2-cbc-md5", "06", CURL_SSLVERSION_SSLv3 }, CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
{ "exp-des-cbc-sha", "09", CURL_SSLVERSION_SSLv3 }, { "exp-rc4-md5", "03",
{ "des-cbc3-sha", "0A", CURL_SSLVERSION_SSLv3 }, CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
{ "aes128-sha", "2F", CURL_SSLVERSION_TLSv1 }, { "rc4-md5", "04",
{ "aes256-sha", "35", CURL_SSLVERSION_TLSv1 }, CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
{ "rc4-md5", "1", CURL_SSLVERSION_SSLv2 }, CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
{ "exp-rc4-md5", "2", CURL_SSLVERSION_SSLv2 }, { "rc4-sha", "05",
{ "rc2-md5", "3", CURL_SSLVERSION_SSLv2 }, CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
{ "exp-rc2-md5", "4", CURL_SSLVERSION_SSLv2 }, CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
{ "des-cbc-md5", "6", CURL_SSLVERSION_SSLv2 }, { "exp-rc2-cbc-md5", "06",
{ "des-cbc3-md5", "7", CURL_SSLVERSION_SSLv2 }, CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
{ "exp-des-cbc-sha", "09",
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
CURL_GSKPROTO_TLSV11_MASK },
{ "des-cbc3-sha", "0A",
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
{ "aes128-sha", "2F",
CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
CURL_GSKPROTO_TLSV12_MASK },
{ "aes256-sha", "35",
CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
CURL_GSKPROTO_TLSV12_MASK },
{ "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
{ "aes128-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
{ "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
{ "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
{ "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
{ "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
{ "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
{ "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
{ "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
{ (const char *) NULL, (const char *) NULL, 0 } { (const char *) NULL, (const char *) NULL, 0 }
}; };
@@ -97,8 +161,8 @@ static bool is_separator(char c)
} }
static CURLcode gskit_status(struct SessionHandle * data, int rc, static CURLcode gskit_status(struct SessionHandle *data, int rc,
const char * procname, CURLcode defcode) const char *procname, CURLcode defcode)
{ {
CURLcode cc; CURLcode cc;
@@ -137,13 +201,13 @@ static CURLcode gskit_status(struct SessionHandle * data, int rc,
default: default:
failf(data, "%s: %s", procname, gsk_strerror(rc)); failf(data, "%s: %s", procname, gsk_strerror(rc));
break; break;
} }
return defcode; return defcode;
} }
static CURLcode set_enum(struct SessionHandle * data, static CURLcode set_enum(struct SessionHandle *data, gsk_handle h,
gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value) GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
{ {
int rc = gsk_attribute_set_enum(h, id, value); int rc = gsk_attribute_set_enum(h, id, value);
@@ -153,6 +217,9 @@ static CURLcode set_enum(struct SessionHandle * data,
case GSK_ERROR_IO: case GSK_ERROR_IO:
failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
break; break;
case GSK_ATTRIBUTE_INVALID_ID:
if(unsupported_ok)
return CURLE_UNSUPPORTED_PROTOCOL;
default: default:
failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
break; break;
@@ -161,8 +228,8 @@ static CURLcode set_enum(struct SessionHandle * data,
} }
static CURLcode set_buffer(struct SessionHandle * data, static CURLcode set_buffer(struct SessionHandle *data, gsk_handle h,
gsk_handle h, GSK_BUF_ID id, const char * buffer) GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
{ {
int rc = gsk_attribute_set_buffer(h, id, buffer, 0); int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
@@ -172,6 +239,9 @@ static CURLcode set_buffer(struct SessionHandle * data,
case GSK_ERROR_IO: case GSK_ERROR_IO:
failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
break; break;
case GSK_ATTRIBUTE_INVALID_ID:
if(unsupported_ok)
return CURLE_UNSUPPORTED_PROTOCOL;
default: default:
failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
break; break;
@@ -180,7 +250,7 @@ static CURLcode set_buffer(struct SessionHandle * data,
} }
static CURLcode set_numeric(struct SessionHandle * data, static CURLcode set_numeric(struct SessionHandle *data,
gsk_handle h, GSK_NUM_ID id, int value) gsk_handle h, GSK_NUM_ID id, int value)
{ {
int rc = gsk_attribute_set_numeric_value(h, id, value); int rc = gsk_attribute_set_numeric_value(h, id, value);
@@ -200,8 +270,8 @@ static CURLcode set_numeric(struct SessionHandle * data,
} }
static CURLcode set_callback(struct SessionHandle * data, static CURLcode set_callback(struct SessionHandle *data,
gsk_handle h, GSK_CALLBACK_ID id, void * info) gsk_handle h, GSK_CALLBACK_ID id, void *info)
{ {
int rc = gsk_attribute_set_callback(h, id, info); int rc = gsk_attribute_set_callback(h, id, info);
@@ -219,17 +289,20 @@ static CURLcode set_callback(struct SessionHandle * data,
} }
static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h) static CURLcode set_ciphers(struct SessionHandle *data,
gsk_handle h, unsigned int *protoflags)
{ {
const char * cipherlist = data->set.str[STRING_SSL_CIPHER_LIST]; const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
char * sslv2ciphers; const char *clp;
char * sslv3ciphers; const gskit_cipher *ctp;
const char * clp;
const gskit_cipher * ctp;
char * v2p;
char * v3p;
int i; int i;
int l;
bool unsupported;
CURLcode cc; CURLcode cc;
struct {
char *buf;
char *ptr;
} ciphers[CURL_GSKPROTO_LAST];
/* Compile cipher list into GSKit-compatible cipher lists. */ /* Compile cipher list into GSKit-compatible cipher lists. */
@@ -243,42 +316,44 @@ static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h)
/* We allocate GSKit buffers of the same size as the input string: since /* We allocate GSKit buffers of the same size as the input string: since
GSKit tokens are always shorter than their cipher names, allocated buffers GSKit tokens are always shorter than their cipher names, allocated buffers
will always be large enough to accomodate the result. */ will always be large enough to accomodate the result. */
i = strlen(cipherlist) + 1; l = strlen(cipherlist) + 1;
v2p = malloc(i); memset((char *) ciphers, 0, sizeof ciphers);
if(!v2p) for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
return CURLE_OUT_OF_MEMORY; ciphers[i].buf = malloc(l);
v3p = malloc(i); if(!ciphers[i].buf) {
if(!v3p) { while(i--)
free(v2p); free(ciphers[i].buf);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
}
ciphers[i].ptr = ciphers[i].buf;
*ciphers[i].ptr = '\0';
} }
sslv2ciphers = v2p;
sslv3ciphers = v3p;
/* Process each cipher in input string. */ /* Process each cipher in input string. */
unsupported = FALSE;
cc = CURLE_OK;
for(;;) { for(;;) {
for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
cipherlist++; cipherlist++;
i = cipherlist - clp; l = cipherlist - clp;
if(!i) if(!l)
break; break;
/* Search the cipher in our table. */ /* Search the cipher in our table. */
for(ctp = ciphertable; ctp->name; ctp++) for(ctp = ciphertable; ctp->name; ctp++)
if(strnequal(ctp->name, clp, i) && !ctp->name[i]) if(strnequal(ctp->name, clp, l) && !ctp->name[l])
break; break;
if(!ctp->name) if(!ctp->name) {
failf(data, "Unknown cipher %.*s: ignored", i, clp); failf(data, "Unknown cipher %.*s", l, clp);
cc = CURLE_SSL_CIPHER;
}
else { else {
switch (ctp->sslver) { unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
case CURL_SSLVERSION_SSLv2: CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
strcpy(v2p, ctp->gsktoken); for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
v2p += strlen(v2p); if(ctp->versions & (1 << i)) {
break; strcpy(ciphers[i].ptr, ctp->gsktoken);
default: ciphers[i].ptr += strlen(ctp->gsktoken);
/* GSKit wants TLSv1 ciphers with SSLv3 ciphers. */ }
strcpy(v3p, ctp->gsktoken);
v3p += strlen(v3p);
break;
} }
} }
@@ -286,13 +361,63 @@ static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h)
while(is_separator(*cipherlist)) while(is_separator(*cipherlist))
cipherlist++; cipherlist++;
} }
*v2p = '\0';
*v3p = '\0'; /* Disable protocols with empty cipher lists. */
cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS, sslv2ciphers); for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
if(cc == CURLE_OK) if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS, sslv3ciphers); *protoflags &= ~(1 << i);
free(sslv2ciphers); ciphers[i].buf[0] = '\0';
free(sslv3ciphers); }
}
/* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
cc = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
cc = CURLE_OK;
if(unsupported) {
failf(data, "TLSv1.1-only ciphers are not yet supported");
cc = CURLE_SSL_CIPHER;
}
}
}
if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
cc = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
cc = CURLE_OK;
if(unsupported) {
failf(data, "TLSv1.2-only ciphers are not yet supported");
cc = CURLE_SSL_CIPHER;
}
}
}
/* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
cc = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
cc = CURLE_OK;
strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
ciphers[CURL_GSKPROTO_TLSV10].ptr);
}
}
/* Set-up other ciphers. */
if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
/* Clean-up. */
for(i = 0; i < CURL_GSKPROTO_LAST; i++)
free(ciphers[i].buf);
return cc; return cc;
} }
@@ -311,10 +436,10 @@ void Curl_gskit_cleanup(void)
} }
static CURLcode init_environment(struct SessionHandle * data, static CURLcode init_environment(struct SessionHandle *data,
gsk_handle * envir, const char * appid, gsk_handle *envir, const char *appid,
const char * file, const char * label, const char *file, const char *label,
const char * password) const char *password)
{ {
int rc; int rc;
CURLcode c; CURLcode c;
@@ -333,15 +458,15 @@ static CURLcode init_environment(struct SessionHandle * data,
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION); c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
if(c == CURLE_OK && appid) if(c == CURLE_OK && appid)
c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid); c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
if(c == CURLE_OK && file) if(c == CURLE_OK && file)
c = set_buffer(data, h, GSK_KEYRING_FILE, file); c = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
if(c == CURLE_OK && label) if(c == CURLE_OK && label)
c = set_buffer(data, h, GSK_KEYRING_LABEL, label); c = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
if(c == CURLE_OK && password) if(c == CURLE_OK && password)
c = set_buffer(data, h, GSK_KEYRING_PW, password); c = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
if(c == CURLE_OK) { if(c == CURLE_OK) {
/* Locate CAs, Client certificate and key according to our settings. /* Locate CAs, Client certificate and key according to our settings.
@@ -359,9 +484,9 @@ static CURLcode init_environment(struct SessionHandle * data,
} }
static void cancel_async_handshake(struct connectdata * conn, int sockindex) static void cancel_async_handshake(struct connectdata *conn, int sockindex)
{ {
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
Qso_OverlappedIO_t cstat; Qso_OverlappedIO_t cstat;
if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
@@ -369,15 +494,15 @@ static void cancel_async_handshake(struct connectdata * conn, int sockindex)
} }
static void close_async_handshake(struct ssl_connect_data * connssl) static void close_async_handshake(struct ssl_connect_data *connssl)
{ {
QsoDestroyIOCompletionPort(connssl->iocport); QsoDestroyIOCompletionPort(connssl->iocport);
connssl->iocport = -1; connssl->iocport = -1;
} }
static void close_one(struct ssl_connect_data * conn, static void close_one(struct ssl_connect_data *conn,
struct SessionHandle * data) struct SessionHandle *data)
{ {
if(conn->handle) { if(conn->handle) {
gskit_status(data, gsk_secure_soc_close(&conn->handle), gskit_status(data, gsk_secure_soc_close(&conn->handle),
@@ -389,10 +514,10 @@ static void close_one(struct ssl_connect_data * conn,
} }
static ssize_t gskit_send(struct connectdata * conn, int sockindex, static ssize_t gskit_send(struct connectdata *conn, int sockindex,
const void * mem, size_t len, CURLcode * curlcode) const void *mem, size_t len, CURLcode *curlcode)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
CURLcode cc; CURLcode cc;
int written; int written;
@@ -408,10 +533,10 @@ static ssize_t gskit_send(struct connectdata * conn, int sockindex,
} }
static ssize_t gskit_recv(struct connectdata * conn, int num, char * buf, static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
size_t buffersize, CURLcode * curlcode) size_t buffersize, CURLcode *curlcode)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
int buffsize; int buffsize;
int nread; int nread;
CURLcode cc; CURLcode cc;
@@ -428,20 +553,18 @@ static ssize_t gskit_recv(struct connectdata * conn, int num, char * buf,
} }
static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex) static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
gsk_handle envir; gsk_handle envir;
CURLcode cc; CURLcode cc;
int rc; int rc;
char * keyringfile; char *keyringfile;
char * keyringpwd; char *keyringpwd;
char * keyringlabel; char *keyringlabel;
char * v2ciphers; char *sni;
char * v3ciphers; unsigned int protoflags;
char * sni;
bool sslv2enable, sslv3enable, tlsv1enable;
long timeout; long timeout;
Qso_OverlappedIO_t commarea; Qso_OverlappedIO_t commarea;
@@ -491,43 +614,39 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
return cc; return cc;
/* Determine which SSL/TLS version should be enabled. */ /* Determine which SSL/TLS version should be enabled. */
sslv2enable = sslv3enable = tlsv1enable = false; protoflags = CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
sni = conn->host.name; sni = conn->host.name;
switch (data->set.ssl.version) { switch (data->set.ssl.version) {
case CURL_SSLVERSION_SSLv2: case CURL_SSLVERSION_SSLv2:
sslv2enable = true; protoflags = CURL_GSKPROTO_SSLV2_MASK;
sni = (char *) NULL; sni = (char *) NULL;
break; break;
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
sslv3enable = true; protoflags = CURL_GSKPROTO_SSLV2_MASK;
sni = (char *) NULL; sni = (char *) NULL;
break; break;
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
tlsv1enable = true; protoflags = CURL_GSKPROTO_TLSV10_MASK |
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
break; break;
default: /* CURL_SSLVERSION_DEFAULT. */ case CURL_SSLVERSION_TLSv1_0:
sslv3enable = true; protoflags = CURL_GSKPROTO_TLSV10_MASK;
tlsv1enable = true; break;
case CURL_SSLVERSION_TLSv1_1:
protoflags = CURL_GSKPROTO_TLSV11_MASK;
break;
case CURL_SSLVERSION_TLSv1_2:
protoflags = CURL_GSKPROTO_TLSV12_MASK;
break; break;
} }
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */ /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
if(sni) { if(sni) {
rc = gsk_attribute_set_buffer(connssl->handle, cc = set_buffer(data, connssl->handle,
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, 0); GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
switch (rc) { if(cc == CURLE_UNSUPPORTED_PROTOCOL)
case GSK_OK: cc = CURLE_OK;
case GSK_ATTRIBUTE_INVALID_ID:
break;
case GSK_ERROR_IO:
failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
cc = CURLE_SSL_CONNECT_ERROR;
break;
default:
failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
cc = CURLE_SSL_CONNECT_ERROR;
break;
}
} }
/* Set session parameters. */ /* Set session parameters. */
@@ -544,23 +663,51 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
if(cc == CURLE_OK) if(cc == CURLE_OK)
cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
if(cc == CURLE_OK) if(cc == CURLE_OK)
cc = set_ciphers(data, connssl->handle); cc = set_ciphers(data, connssl->handle, &protoflags);
if(!protoflags) {
failf(data, "No SSL protocol/cipher combination enabled");
cc = CURLE_SSL_CIPHER;
}
if(cc == CURLE_OK) if(cc == CURLE_OK)
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
sslv2enable? GSK_PROTOCOL_SSLV2_ON: (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
GSK_PROTOCOL_SSLV2_OFF); GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
if(cc == CURLE_OK) if(cc == CURLE_OK)
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
sslv3enable? GSK_PROTOCOL_SSLV3_ON: (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
GSK_PROTOCOL_SSLV3_OFF); GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
if(cc == CURLE_OK) if(cc == CURLE_OK)
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
sslv3enable? GSK_PROTOCOL_TLSV1_ON: (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
GSK_PROTOCOL_TLSV1_OFF); GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
if(cc == CURLE_OK) {
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
(protoflags & CURL_GSKPROTO_TLSV11_MASK)?
GSK_TRUE: GSK_FALSE, TRUE);
if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
cc = CURLE_OK;
if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
failf(data, "TLS 1.1 not yet supported");
cc = CURLE_SSL_CIPHER;
}
}
}
if(cc == CURLE_OK) {
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
(protoflags & CURL_GSKPROTO_TLSV12_MASK)?
GSK_TRUE: GSK_FALSE, TRUE);
if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
cc = CURLE_OK;
if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
failf(data, "TLS 1.2 not yet supported");
cc = CURLE_SSL_CIPHER;
}
}
}
if(cc == CURLE_OK) if(cc == CURLE_OK)
cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
GSK_SERVER_AUTH_PASSTHRU); GSK_SERVER_AUTH_PASSTHRU, FALSE);
if(cc == CURLE_OK) { if(cc == CURLE_OK) {
/* Start handshake. Try asynchronous first. */ /* Start handshake. Try asynchronous first. */
@@ -596,11 +743,11 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
} }
static CURLcode gskit_connect_step2(struct connectdata * conn, int sockindex, static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
bool nonblocking) bool nonblocking)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
Qso_OverlappedIO_t cstat; Qso_OverlappedIO_t cstat;
long timeout_ms; long timeout_ms;
struct timeval stmv; struct timeval stmv;
@@ -648,15 +795,15 @@ static CURLcode gskit_connect_step2(struct connectdata * conn, int sockindex,
} }
static CURLcode gskit_connect_step3(struct connectdata * conn, int sockindex) static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
const gsk_cert_data_elem * cdev; const gsk_cert_data_elem *cdev;
int cdec; int cdec;
const gsk_cert_data_elem * p; const gsk_cert_data_elem *p;
const char * cert = (const char *) NULL; const char *cert = (const char *) NULL;
const char * certend; const char *certend;
int i; int i;
CURLcode cc; CURLcode cc;
@@ -715,11 +862,11 @@ static CURLcode gskit_connect_step3(struct connectdata * conn, int sockindex)
} }
static CURLcode gskit_connect_common(struct connectdata * conn, int sockindex, static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
bool nonblocking, bool * done) bool nonblocking, bool *done)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
long timeout_ms; long timeout_ms;
Qso_OverlappedIO_t cstat; Qso_OverlappedIO_t cstat;
CURLcode cc = CURLE_OK; CURLcode cc = CURLE_OK;
@@ -774,9 +921,9 @@ static CURLcode gskit_connect_common(struct connectdata * conn, int sockindex,
} }
CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn, CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
int sockindex, int sockindex,
bool * done) bool *done)
{ {
CURLcode cc; CURLcode cc;
@@ -787,7 +934,7 @@ CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn,
} }
CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex) CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
{ {
CURLcode retcode; CURLcode retcode;
bool done; bool done;
@@ -803,17 +950,17 @@ CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex)
} }
void Curl_gskit_close(struct connectdata * conn, int sockindex) void Curl_gskit_close(struct connectdata *conn, int sockindex)
{ {
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->use) if(connssl->use)
close_one(connssl, data); close_one(connssl, data);
} }
int Curl_gskit_close_all(struct SessionHandle * data) int Curl_gskit_close_all(struct SessionHandle *data)
{ {
/* Unimplemented. */ /* Unimplemented. */
(void) data; (void) data;
@@ -821,10 +968,10 @@ int Curl_gskit_close_all(struct SessionHandle * data)
} }
int Curl_gskit_shutdown(struct connectdata * conn, int sockindex) int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
{ {
struct ssl_connect_data * connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct SessionHandle * data = conn->data; struct SessionHandle *data = conn->data;
ssize_t nread; ssize_t nread;
int what; int what;
int rc; int rc;
@@ -875,14 +1022,14 @@ int Curl_gskit_shutdown(struct connectdata * conn, int sockindex)
} }
size_t Curl_gskit_version(char * buffer, size_t size) size_t Curl_gskit_version(char *buffer, size_t size)
{ {
strncpy(buffer, "GSKit", size); strncpy(buffer, "GSKit", size);
return strlen(buffer); return strlen(buffer);
} }
int Curl_gskit_check_cxn(struct connectdata * cxn) int Curl_gskit_check_cxn(struct connectdata *cxn)
{ {
int err; int err;
int errlen; int errlen;

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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -633,10 +633,8 @@ gtls_connect_step3(struct connectdata *conn,
else else
infof(data, "\t server certificate verification OK\n"); infof(data, "\t server certificate verification OK\n");
} }
else { else
infof(data, "\t server certificate verification SKIPPED\n"); infof(data, "\t server certificate verification SKIPPED\n");
goto after_server_cert_verification;
}
/* initialize an X.509 certificate structure. */ /* initialize an X.509 certificate structure. */
gnutls_x509_crt_init(&x509_cert); gnutls_x509_crt_init(&x509_cert);
@@ -766,8 +764,6 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_x509_crt_deinit(x509_cert); gnutls_x509_crt_deinit(x509_cert);
after_server_cert_verification:
/* compression algorithm (if any) */ /* compression algorithm (if any) */
ptr = gnutls_compression_get_name(gnutls_compression_get(session)); ptr = gnutls_compression_get_name(gnutls_compression_get(session));
/* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */

View File

@@ -23,7 +23,7 @@
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \ #if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
defined(USE_GSKIT) defined(USE_GSKIT) || defined(USE_NSS)
/* these backends use functions from this file */ /* these backends use functions from this file */
#include "hostcheck.h" #include "hostcheck.h"
@@ -94,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
return 0; return 0;
} }
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */ #endif /* SSLEAY or AXTLS or QSOSSL or GSKIT or NSS */

View File

@@ -291,9 +291,10 @@ remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
{ {
struct hostcache_prune_data user; struct hostcache_prune_data user;
if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache) if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache ||
/* cache forever means never prune, and NULL hostcache means dns->inuse)
we can't do it */ /* cache forever means never prune, and NULL hostcache means we can't do
it, if it still is in use then we leave it */
return 0; return 0;
time(&user.now); time(&user.now);
@@ -428,9 +429,13 @@ int Curl_resolv(struct connectdata *conn,
/* free the allocated entry_id again */ /* free the allocated entry_id again */
free(entry_id); free(entry_id);
infof(data, "Hostname was %sfound in DNS cache\n", dns?"":"NOT ");
/* See whether the returned entry is stale. Done before we release lock */ /* See whether the returned entry is stale. Done before we release lock */
if(remove_entry_if_stale(data, dns)) if(remove_entry_if_stale(data, dns)) {
infof(data, "Hostname in DNS cache was stale, zapped\n");
dns = NULL; /* the memory deallocation is being handled by the hash */ dns = NULL; /* the memory deallocation is being handled by the hash */
}
if(dns) { if(dns) {
dns->inuse++; /* we use it! */ dns->inuse++; /* we use it! */

View File

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

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -140,7 +140,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
#if defined(HAVE_GETADDRINFO_THREADSAFE) #if defined(HAVE_GETADDRINFO_THREADSAFE)
else { else {
struct addrinfo hints; struct addrinfo hints;
char sbuf[NI_MAXSERV]; char sbuf[12];
char *sbufptr = NULL; char *sbufptr = NULL;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -168,7 +168,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct addrinfo hints; struct addrinfo hints;
Curl_addrinfo *res; Curl_addrinfo *res;
int error; int error;
char sbuf[NI_MAXSERV]; char sbuf[12];
char *sbufptr = NULL; char *sbufptr = NULL;
char addrbuf[128]; char addrbuf[128];
int pf; int pf;

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -72,4 +72,40 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
} }
/*
* Function provided by the resolver backend to set
* outgoing interface to use for DNS requests
*/
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
const char *interf)
{
(void)data;
(void)interf;
return CURLE_NOT_BUILT_IN;
}
/*
* Function provided by the resolver backend to set
* local IPv4 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
const char *local_ip4)
{
(void)data;
(void)local_ip4;
return CURLE_NOT_BUILT_IN;
}
/*
* Function provided by the resolver backend to set
* local IPv6 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
const char *local_ip6)
{
(void)data;
(void)local_ip6;
return CURLE_NOT_BUILT_IN;
}
#endif /* truly sync */ #endif /* truly sync */

View File

@@ -75,6 +75,7 @@
#include "non-ascii.h" #include "non-ascii.h"
#include "bundles.h" #include "bundles.h"
#include "pipeline.h" #include "pipeline.h"
#include "http2.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -105,7 +106,7 @@ static int https_getsock(struct connectdata *conn,
*/ */
const struct Curl_handler Curl_handler_http = { const struct Curl_handler Curl_handler_http = {
"HTTP", /* scheme */ "HTTP", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_http = {
*/ */
const struct Curl_handler Curl_handler_https = { const struct Curl_handler Curl_handler_https = {
"HTTPS", /* scheme */ "HTTPS", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -149,6 +150,19 @@ const struct Curl_handler Curl_handler_https = {
#endif #endif
CURLcode Curl_http_setup_conn(struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the SessionHandle, only to survive
during this request */
DEBUGASSERT(conn->data->req.protop == NULL);
conn->data->req.protop = calloc(1, sizeof(struct HTTP));
if(!conn->data->req.protop)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
/* /*
* checkheaders() checks the linked list of custom HTTP headers for a * checkheaders() checks the linked list of custom HTTP headers for a
* particular header (prefix). * particular header (prefix).
@@ -173,25 +187,25 @@ char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader)
* case of allocation failure. Returns an empty string if the header value * case of allocation failure. Returns an empty string if the header value
* consists entirely of whitespace. * consists entirely of whitespace.
*/ */
static char *copy_header_value(const char *h) char *Curl_copy_header_value(const char *header)
{ {
const char *start; const char *start;
const char *end; const char *end;
char *value; char *value;
size_t len; size_t len;
DEBUGASSERT(h); DEBUGASSERT(header);
/* Find the end of the header name */ /* Find the end of the header name */
while(*h && (*h != ':')) while(*header && (*header != ':'))
++h; ++header;
if(*h) if(*header)
/* Skip over colon */ /* Skip over colon */
++h; ++header;
/* Find the first non-space letter */ /* Find the first non-space letter */
start = h; start = header;
while(*start && ISSPACE(*start)) while(*start && ISSPACE(*start))
start++; start++;
@@ -210,7 +224,7 @@ static char *copy_header_value(const char *h)
end--; end--;
/* get length of the type */ /* get length of the type */
len = end-start+1; len = end - start + 1;
value = malloc(len + 1); value = malloc(len + 1);
if(!value) if(!value)
@@ -330,7 +344,7 @@ static bool pickoneauth(struct auth *pick)
static CURLcode http_perhapsrewind(struct connectdata *conn) static CURLcode http_perhapsrewind(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct HTTP *http = data->state.proto.http; struct HTTP *http = data->req.protop;
curl_off_t bytessent; curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */ curl_off_t expectsend = -1; /* default is unknown */
@@ -685,9 +699,8 @@ Curl_http_output_auth(struct connectdata *conn,
* proxy CONNECT loop. * proxy CONNECT loop.
*/ */
CURLcode Curl_http_input_auth(struct connectdata *conn, CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
int httpcode, const char *auth) /* the first non-space */
const char *header) /* the first non-space */
{ {
/* /*
* This resource requires authentication * This resource requires authentication
@@ -695,24 +708,17 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
unsigned long *availp; unsigned long *availp;
const char *start;
struct auth *authp; struct auth *authp;
if(httpcode == 407) { if(proxy) {
start = header+strlen("Proxy-authenticate:");
availp = &data->info.proxyauthavail; availp = &data->info.proxyauthavail;
authp = &data->state.authproxy; authp = &data->state.authproxy;
} }
else { else {
start = header+strlen("WWW-Authenticate:");
availp = &data->info.httpauthavail; availp = &data->info.httpauthavail;
authp = &data->state.authhost; authp = &data->state.authhost;
} }
/* pass all white spaces */
while(*start && ISSPACE(*start))
start++;
/* /*
* Here we check if we want the specific single authentication (using ==) and * Here we check if we want the specific single authentication (using ==) and
* if we do, we initiate usage of it. * if we do, we initiate usage of it.
@@ -730,10 +736,10 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
* *
*/ */
while(*start) { while(*auth) {
#ifdef USE_HTTP_NEGOTIATE #ifdef USE_HTTP_NEGOTIATE
if(checkprefix("GSS-Negotiate", start) || if(checkprefix("GSS-Negotiate", auth) ||
checkprefix("Negotiate", start)) { checkprefix("Negotiate", auth)) {
int neg; int neg;
*availp |= CURLAUTH_GSSNEGOTIATE; *availp |= CURLAUTH_GSSNEGOTIATE;
authp->avail |= CURLAUTH_GSSNEGOTIATE; authp->avail |= CURLAUTH_GSSNEGOTIATE;
@@ -746,7 +752,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
data->state.authproblem = TRUE; data->state.authproblem = TRUE;
} }
else { else {
neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start); neg = Curl_input_negotiate(conn, proxy, auth);
if(neg == 0) { if(neg == 0) {
DEBUGASSERT(!data->req.newurl); DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url); data->req.newurl = strdup(data->change.url);
@@ -765,14 +771,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
#endif #endif
#ifdef USE_NTLM #ifdef USE_NTLM
/* NTLM support requires the SSL crypto libs */ /* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", start)) { if(checkprefix("NTLM", auth)) {
*availp |= CURLAUTH_NTLM; *availp |= CURLAUTH_NTLM;
authp->avail |= CURLAUTH_NTLM; authp->avail |= CURLAUTH_NTLM;
if(authp->picked == CURLAUTH_NTLM || if(authp->picked == CURLAUTH_NTLM ||
authp->picked == CURLAUTH_NTLM_WB) { authp->picked == CURLAUTH_NTLM_WB) {
/* NTLM authentication is picked and activated */ /* NTLM authentication is picked and activated */
CURLcode ntlm = CURLcode ntlm =
Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start); Curl_input_ntlm(conn, proxy, auth);
if(CURLE_OK == ntlm) { if(CURLE_OK == ntlm) {
data->state.authproblem = FALSE; data->state.authproblem = FALSE;
#ifdef NTLM_WB_ENABLED #ifdef NTLM_WB_ENABLED
@@ -784,14 +790,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
/* Get the challenge-message which will be passed to /* Get the challenge-message which will be passed to
* ntlm_auth for generating the type 3 message later */ * ntlm_auth for generating the type 3 message later */
while(*start && ISSPACE(*start)) while(*auth && ISSPACE(*auth))
start++; auth++;
if(checkprefix("NTLM", start)) { if(checkprefix("NTLM", auth)) {
start += strlen("NTLM"); auth += strlen("NTLM");
while(*start && ISSPACE(*start)) while(*auth && ISSPACE(*auth))
start++; auth++;
if(*start) if(*auth)
if((conn->challenge_header = strdup(start)) == NULL) if((conn->challenge_header = strdup(auth)) == NULL)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
} }
@@ -806,7 +812,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
else else
#endif #endif
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
if(checkprefix("Digest", start)) { if(checkprefix("Digest", auth)) {
if((authp->avail & CURLAUTH_DIGEST) != 0) { if((authp->avail & CURLAUTH_DIGEST) != 0) {
infof(data, "Ignoring duplicate digest auth header.\n"); infof(data, "Ignoring duplicate digest auth header.\n");
} }
@@ -819,7 +825,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
* authentication isn't activated yet, as we need to store the * authentication isn't activated yet, as we need to store the
* incoming data from this header in case we are gonna use * incoming data from this header in case we are gonna use
* Digest. */ * Digest. */
dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start); dig = Curl_input_digest(conn, proxy, auth);
if(CURLDIGEST_FINE != dig) { if(CURLDIGEST_FINE != dig) {
infof(data, "Authentication problem. Ignoring this.\n"); infof(data, "Authentication problem. Ignoring this.\n");
@@ -829,7 +835,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
} }
else else
#endif #endif
if(checkprefix("Basic", start)) { if(checkprefix("Basic", auth)) {
*availp |= CURLAUTH_BASIC; *availp |= CURLAUTH_BASIC;
authp->avail |= CURLAUTH_BASIC; authp->avail |= CURLAUTH_BASIC;
if(authp->picked == CURLAUTH_BASIC) { if(authp->picked == CURLAUTH_BASIC) {
@@ -843,12 +849,12 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
} }
/* there may be multiple methods on one line, so keep reading */ /* there may be multiple methods on one line, so keep reading */
while(*start && *start != ',') /* read up to the next comma */ while(*auth && *auth != ',') /* read up to the next comma */
start++; auth++;
if(*start == ',') /* if we're on a comma, skip it */ if(*auth == ',') /* if we're on a comma, skip it */
start++; auth++;
while(*start && ISSPACE(*start)) while(*auth && ISSPACE(*auth))
start++; auth++;
} }
return CURLE_OK; return CURLE_OK;
} }
@@ -948,7 +954,7 @@ static size_t readmoredata(char *buffer,
void *userp) void *userp)
{ {
struct connectdata *conn = (struct connectdata *)userp; struct connectdata *conn = (struct connectdata *)userp;
struct HTTP *http = conn->data->state.proto.http; struct HTTP *http = conn->data->req.protop;
size_t fullsize = size * nitems; size_t fullsize = size * nitems;
if(0 == http->postsize) if(0 == http->postsize)
@@ -1019,7 +1025,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
CURLcode res; CURLcode res;
char *ptr; char *ptr;
size_t size; size_t size;
struct HTTP *http = conn->data->state.proto.http; struct HTTP *http = conn->data->req.protop;
size_t sendsize; size_t sendsize;
curl_socket_t sockfd; curl_socket_t sockfd;
size_t headersize; size_t headersize;
@@ -1402,7 +1408,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
CURLcode status, bool premature) CURLcode status, bool premature)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct HTTP *http =data->state.proto.http; struct HTTP *http =data->req.protop;
Curl_unencode_cleanup(conn); Curl_unencode_cleanup(conn);
@@ -1442,6 +1448,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
if(!premature && /* this check is pointless when DONE is called before the if(!premature && /* this check is pointless when DONE is called before the
entire operation is complete */ entire operation is complete */
!conn->bits.retry && !conn->bits.retry &&
!data->set.connect_only &&
((http->readbytecount + ((http->readbytecount +
data->req.headerbytecount - data->req.headerbytecount -
data->req.deductheadercount)) <= 0) { data->req.deductheadercount)) <= 0) {
@@ -1456,14 +1463,19 @@ CURLcode Curl_http_done(struct connectdata *conn,
} }
/* Determine if we should use HTTP 1.1 for this request. Reasons to avoid it /*
are if the user specifically requested HTTP 1.0, if the server we are * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
connected to only supports 1.0, or if any server previously contacted to * to avoid it include:
handle this request only supports 1.0. */ *
static bool use_http_1_1(const struct SessionHandle *data, * - if the user specifically requested HTTP 1.0
const struct connectdata *conn) * - if the server we are connected to only supports 1.0
* - if any server previously contacted to handle this request only supports
* 1.0.
*/
static bool use_http_1_1plus(const struct SessionHandle *data,
const struct connectdata *conn)
{ {
return ((data->set.httpversion == CURL_HTTP_VERSION_1_1) || return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
((data->set.httpversion != CURL_HTTP_VERSION_1_0) && ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
((conn->httpversion == 11) || ((conn->httpversion == 11) ||
((conn->httpversion != 10) && ((conn->httpversion != 10) &&
@@ -1479,7 +1491,7 @@ static CURLcode expect100(struct SessionHandle *data,
const char *ptr; const char *ptr;
data->state.expect100header = FALSE; /* default to false unless it is set data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */ to TRUE below */
if(use_http_1_1(data, conn)) { if(use_http_1_1plus(data, conn)) {
/* if not doing HTTP 1.0 or disabled explicitly, we add a Expect: /* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
100-continue to the headers which actually speeds up post operations 100-continue to the headers which actually speeds up post operations
(as there is one packet coming back from the web server) */ (as there is one packet coming back from the web server) */
@@ -1655,20 +1667,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the rest of the request in the PERFORM phase. */ the rest of the request in the PERFORM phase. */
*done = TRUE; *done = TRUE;
/* If there already is a protocol-specific struct allocated for this http = data->req.protop;
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
if(!data->state.proto.http) {
/* Only allocate this struct if we don't already have it! */
http = calloc(1, sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
data->state.proto.http = http;
}
else
http = data->state.proto.http;
if(!data->state.this_is_a_follow) { if(!data->state.this_is_a_follow) {
/* this is not a followed location, get the original host name */ /* this is not a followed location, get the original host name */
@@ -1795,7 +1794,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(conn->bits.authneg) if(conn->bits.authneg)
/* don't enable chunked during auth neg */ /* don't enable chunked during auth neg */
; ;
else if(use_http_1_1(data, conn)) { else if(use_http_1_1plus(data, conn)) {
/* HTTP, upload, unknown file size and not HTTP 1.0 */ /* HTTP, upload, unknown file size and not HTTP 1.0 */
data->req.upload_chunky = TRUE; data->req.upload_chunky = TRUE;
} }
@@ -1824,7 +1823,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
custom Host: header if this is NOT a redirect, as setting Host: in the custom Host: header if this is NOT a redirect, as setting Host: in the
redirected request is being out on thin ice. Except if the host name redirected request is being out on thin ice. Except if the host name
is the same as the first one! */ is the same as the first one! */
char *cookiehost = copy_header_value(ptr); char *cookiehost = Curl_copy_header_value(ptr);
if(!cookiehost) if(!cookiehost)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
if(!*cookiehost) if(!*cookiehost)
@@ -2095,7 +2094,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Use 1.1 unless the user specifically asked for 1.0 or the server only /* Use 1.1 unless the user specifically asked for 1.0 or the server only
supports 1.0 */ supports 1.0 */
httpstring= use_http_1_1(data, conn)?"1.1":"1.0"; httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
/* initialize a dynamic send-buffer */ /* initialize a dynamic send-buffer */
req_buffer = Curl_add_buffer_init(); req_buffer = Curl_add_buffer_init();
@@ -2173,6 +2172,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
if(!(conn->handler->flags&PROTOPT_SSL) &&
(data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
/* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
over SSL */
result = Curl_http2_request(req_buffer, conn);
if(result)
return result;
}
#if !defined(CURL_DISABLE_COOKIES) #if !defined(CURL_DISABLE_COOKIES)
if(data->cookies || addcookies) { if(data->cookies || addcookies) {
struct Cookie *co=NULL; /* no cookies from start */ struct Cookie *co=NULL; /* no cookies from start */
@@ -3231,7 +3239,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
} }
/* check for Content-Type: header lines to get the MIME-type */ /* check for Content-Type: header lines to get the MIME-type */
else if(checkprefix("Content-Type:", k->p)) { else if(checkprefix("Content-Type:", k->p)) {
char *contenttype = copy_header_value(k->p); char *contenttype = Curl_copy_header_value(k->p);
if(!contenttype) if(!contenttype)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
if(!*contenttype) if(!*contenttype)
@@ -3243,7 +3251,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
} }
} }
else if(checkprefix("Server:", k->p)) { else if(checkprefix("Server:", k->p)) {
char *server_name = copy_header_value(k->p); char *server_name = Curl_copy_header_value(k->p);
/* Turn off pipelining if the server version is blacklisted */ /* Turn off pipelining if the server version is blacklisted */
if(conn->bundle && conn->bundle->server_supports_pipelining) { if(conn->bundle && conn->bundle->server_supports_pipelining) {
@@ -3439,7 +3447,16 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
(401 == k->httpcode)) || (401 == k->httpcode)) ||
(checkprefix("Proxy-authenticate:", k->p) && (checkprefix("Proxy-authenticate:", k->p) &&
(407 == k->httpcode))) { (407 == k->httpcode))) {
result = Curl_http_input_auth(conn, k->httpcode, k->p);
bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
char *auth = Curl_copy_header_value(k->p);
if(!auth)
return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(conn, proxy, auth);
Curl_safefree(auth);
if(result) if(result)
return result; return result;
} }
@@ -3447,7 +3464,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
checkprefix("Location:", k->p) && checkprefix("Location:", k->p) &&
!data->req.location) { !data->req.location) {
/* this is the URL that the server advises us to use instead */ /* this is the URL that the server advises us to use instead */
char *location = copy_header_value(k->p); char *location = Curl_copy_header_value(k->p);
if(!location) if(!location)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
if(!*location) if(!*location)

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -21,19 +21,26 @@
* KIND, either express or implied. * KIND, either express or implied.
* *
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h"
#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_HTTP
#ifdef USE_NGHTTP2
#include <nghttp2/nghttp2.h>
#endif
extern const struct Curl_handler Curl_handler_http; extern const struct Curl_handler Curl_handler_http;
#ifdef USE_SSL #ifdef USE_SSL
extern const struct Curl_handler Curl_handler_https; extern const struct Curl_handler Curl_handler_https;
#endif #endif
/* Header specific functions */
bool Curl_compareheader(const char *headerline, /* line to check */ bool Curl_compareheader(const char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */ const char *header, /* header keyword _with_ colon */
const char *content); /* content string to find */ const char *content); /* content string to find */
char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader); char *Curl_checkheaders(struct SessionHandle *data, const char *thisheader);
char *Curl_copy_header_value(const char *header);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
@@ -66,6 +73,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
CURLcode Curl_http(struct connectdata *conn, bool *done); CURLcode Curl_http(struct connectdata *conn, bool *done);
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
CURLcode Curl_http_connect(struct connectdata *conn, bool *done); CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
CURLcode Curl_http_setup_conn(struct connectdata *conn);
/* The following functions are defined in http_chunks.c */ /* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn); void Curl_httpchunk_init(struct connectdata *conn);
@@ -74,8 +82,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
/* These functions are in http.c */ /* These functions are in http.c */
void Curl_http_auth_stage(struct SessionHandle *data, int stage); void Curl_http_auth_stage(struct SessionHandle *data, int stage);
CURLcode Curl_http_input_auth(struct connectdata *conn, CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
int httpcode, const char *header); const char *auth);
CURLcode Curl_http_auth_act(struct connectdata *conn); CURLcode Curl_http_auth_act(struct connectdata *conn);
CURLcode Curl_http_perhapsrewind(struct connectdata *conn); CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
@@ -141,6 +149,14 @@ struct HTTP {
points to an allocated send_buffer struct */ points to an allocated send_buffer struct */
}; };
struct http_conn {
#ifdef USE_NGHTTP2
nghttp2_session *h2;
#else
int unused; /* prevent a compiler warning */
#endif
};
CURLcode Curl_http_readwrite_headers(struct SessionHandle *data, CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
struct connectdata *conn, struct connectdata *conn,
ssize_t *nread, ssize_t *nread,

182
lib/http2.c Normal file
View File

@@ -0,0 +1,182 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_NGHTTP2
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#include <nghttp2/nghttp2.h>
#include "urldata.h"
#include "http2.h"
#include "http.h"
#include "sendf.h"
#include "curl_base64.h"
#include "curl_memory.h"
/* include memdebug.h last */
#include "memdebug.h"
/*
* Store nghttp2 version info in this buffer, Prefix with a space. Return
* total length written.
*/
int Curl_http2_ver(char *p, size_t len)
{
nghttp2_info *h2 = nghttp2_version(0);
return snprintf(p, len, " nghttp2/%s", h2->version_str);
}
/*
* The implementation of nghttp2_send_callback type. Here we write |data| with
* size |length| to the network and return the number of bytes actually
* written. See the documentation of nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *h2,
const uint8_t *data, size_t length, int flags,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
ssize_t written;
CURLcode rc =
Curl_write(conn, conn->sock[0], data, length, &written);
(void)h2;
(void)flags;
if(rc) {
failf(conn->data, "Failed sending HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
else if(!written)
return NGHTTP2_ERR_WOULDBLOCK;
return written;
}
/*
* The implementation of nghttp2_recv_callback type. Here we read data from
* the network and write them in |buf|. The capacity of |buf| is |length|
* bytes. Returns the number of bytes stored in |buf|. See the documentation
* of nghttp2_recv_callback for the details.
*/
static ssize_t recv_callback(nghttp2_session *h2,
uint8_t *buf, size_t length, int flags,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
ssize_t nread;
CURLcode rc = Curl_read(conn, conn->sock[0], (char *)buf, length, &nread);
(void)h2;
(void)flags;
if(rc) {
failf(conn->data, "Failed recving HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
if(!nread)
return NGHTTP2_ERR_WOULDBLOCK;
return nread;
}
/*
* This is all callbacks nghttp2 calls
*/
static const nghttp2_session_callbacks callbacks = {
send_callback,
recv_callback,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
/*
* The HTTP2 settings we send in the Upgrade request
*/
static nghttp2_settings_entry settings[] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
{ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
};
/*
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
*/
CURLcode Curl_http2_request(Curl_send_buffer *req,
struct connectdata *conn)
{
uint8_t binsettings[80];
CURLcode result;
ssize_t binlen;
char *base64;
size_t blen;
if(!conn->proto.httpc.h2) {
/* The nghttp2 session is not yet setup, do it */
int rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
&callbacks, &conn);
if(rc) {
failf(conn->data, "Couldn't initialize nghttp2!");
return CURLE_OUT_OF_MEMORY; /* most likely at least */
}
}
/* As long as we have a fixed set of settings, we don't have to dynamically
* figure out the base64 strings since it'll always be the same. However,
* the settings will likely not be fixed every time in the future.
*/
/* this returns number of bytes it wrote */
binlen = nghttp2_pack_settings_payload(binsettings,
sizeof(binsettings),
settings,
sizeof(settings)/sizeof(settings[0]));
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
return CURLE_FAILED_INIT;
}
result = Curl_base64_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen);
if(result)
return result;
result = Curl_add_bufferf(req,
"Connection: Upgrade, HTTP2-Settings\r\n"
"Upgrade: %s\r\n"
"HTTP2-Settings: %s\r\n",
NGHTTP2_PROTO_VERSION_ID, base64);
free(base64);
return result;
}
#endif

42
lib/http2.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef HEADER_CURL_HTTP2_H
#define HEADER_CURL_HTTP2_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_NGHTTP2
#include "http.h"
/*
* Store nghttp2 version info in this buffer, Prefix with a space. Return
* total length written.
*/
int Curl_http2_ver(char *p, size_t len);
CURLcode Curl_http2_request(Curl_send_buffer *req,
struct connectdata *conn);
#else /* USE_NGHTTP2 */
#define Curl_http2_request(x,y) CURLE_OK
#endif
#endif /* HEADER_CURL_HTTP2_H */

View File

@@ -141,10 +141,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
d = &data->state.digest; d = &data->state.digest;
} }
/* skip initial whitespaces */
while(*header && ISSPACE(*header))
header++;
if(checkprefix("Digest", header)) { if(checkprefix("Digest", header)) {
header += strlen("Digest"); header += strlen("Digest");
@@ -306,6 +302,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
/* We have a Digest setup for this, use it! Now, to get all the details for /* We have a Digest setup for this, use it! Now, to get all the details for
this sorted out, I must urge you dear friend to read up on the RFC2617 this sorted out, I must urge you dear friend to read up on the RFC2617
section 3.2.2, */ section 3.2.2, */
size_t urilen;
unsigned char md5buf[16]; /* 16 bytes/128 bits */ unsigned char md5buf[16]; /* 16 bytes/128 bits */
unsigned char request_digest[33]; unsigned char request_digest[33];
unsigned char *md5this; unsigned char *md5this;
@@ -440,13 +437,13 @@ CURLcode Curl_output_digest(struct connectdata *conn,
Further details on Digest implementation differences: Further details on Digest implementation differences:
http://www.fngtps.com/2006/09/http-authentication http://www.fngtps.com/2006/09/http-authentication
*/ */
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
md5this = (unsigned char *)aprintf("%s:%.*s", request, if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL))
curlx_sztosi(tmp - (char *)uripath), urilen = tmp - (char *)uripath;
uripath);
}
else else
md5this = (unsigned char *)aprintf("%s:%s", request, uripath); urilen = strlen((char *)uripath);
md5this = (unsigned char *)aprintf("%s:%.*s", request, urilen, uripath);
if(d->qop && Curl_raw_equal(d->qop, "auth-int")) { if(d->qop && Curl_raw_equal(d->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment. /* We don't support auth-int for PUT or POST at the moment.
@@ -511,7 +508,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
"username=\"%s\", " "username=\"%s\", "
"realm=\"%s\", " "realm=\"%s\", "
"nonce=\"%s\", " "nonce=\"%s\", "
"uri=\"%s\", " "uri=\"%.*s\", "
"cnonce=\"%s\", " "cnonce=\"%s\", "
"nc=%08x, " "nc=%08x, "
"qop=%s, " "qop=%s, "
@@ -520,7 +517,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
userp_quoted, userp_quoted,
d->realm, d->realm,
d->nonce, d->nonce,
uripath, /* this is the PATH part of the URL */ urilen, uripath, /* this is the PATH part of the URL */
d->cnonce, d->cnonce,
d->nc, d->nc,
d->qop, d->qop,
@@ -537,13 +534,13 @@ CURLcode Curl_output_digest(struct connectdata *conn,
"username=\"%s\", " "username=\"%s\", "
"realm=\"%s\", " "realm=\"%s\", "
"nonce=\"%s\", " "nonce=\"%s\", "
"uri=\"%s\", " "uri=\"%.*s\", "
"response=\"%s\"", "response=\"%s\"",
proxy?"Proxy-":"", proxy?"Proxy-":"",
userp_quoted, userp_quoted,
d->realm, d->realm,
d->nonce, d->nonce,
uripath, /* this is the PATH part of the URL */ urilen, uripath, /* this is the PATH part of the URL */
request_digest); request_digest);
} }
Curl_safefree(userp_quoted); Curl_safefree(userp_quoted);

View File

@@ -145,8 +145,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
const char* protocol; const char* protocol;
CURLcode error; CURLcode error;
while(*header && ISSPACE(*header))
header++;
if(checkprefix("GSS-Negotiate", header)) { if(checkprefix("GSS-Negotiate", header)) {
protocol = "GSS-Negotiate"; protocol = "GSS-Negotiate";
gss = TRUE; gss = TRUE;

View File

@@ -98,9 +98,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
const char* protocol; const char* protocol;
CURLcode error; CURLcode error;
while(*header && ISSPACE(*header))
header++;
if(checkprefix("GSS-Negotiate", header)) { if(checkprefix("GSS-Negotiate", header)) {
protocol = "GSS-Negotiate"; protocol = "GSS-Negotiate";
gss = TRUE; gss = TRUE;

View File

@@ -66,13 +66,13 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
* This function might be called several times in the multi interface case * This function might be called several times in the multi interface case
* if the proxy's CONNTECT response is not instant. * if the proxy's CONNTECT response is not instant.
*/ */
prot_save = conn->data->state.proto.generic; prot_save = conn->data->req.protop;
memset(&http_proxy, 0, sizeof(http_proxy)); memset(&http_proxy, 0, sizeof(http_proxy));
conn->data->state.proto.http = &http_proxy; conn->data->req.protop = &http_proxy;
conn->bits.close = FALSE; conn->bits.close = FALSE;
result = Curl_proxyCONNECT(conn, FIRSTSOCKET, result = Curl_proxyCONNECT(conn, FIRSTSOCKET,
conn->host.name, conn->remote_port); conn->host.name, conn->remote_port);
conn->data->state.proto.generic = prot_save; conn->data->req.protop = prot_save;
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
#else #else
@@ -452,8 +452,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
(401 == k->httpcode)) || (401 == k->httpcode)) ||
(checkprefix("Proxy-authenticate:", line_start) && (checkprefix("Proxy-authenticate:", line_start) &&
(407 == k->httpcode))) { (407 == k->httpcode))) {
result = Curl_http_input_auth(conn, k->httpcode,
line_start); bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
char *auth = Curl_copy_header_value(line_start);
if(!auth)
return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(conn, proxy, auth);
Curl_safefree(auth);
if(result) if(result)
return result; return result;
} }

View File

@@ -26,6 +26,8 @@
* RFC4616 PLAIN authentication * RFC4616 PLAIN authentication
* RFC4959 IMAP Extension for SASL Initial Client Response * RFC4959 IMAP Extension for SASL Initial Client Response
* RFC5092 IMAP URL Scheme * RFC5092 IMAP URL Scheme
* RFC6749 OAuth 2.0 Authorization Framework
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -163,7 +165,7 @@ const struct Curl_handler Curl_handler_imaps = {
static const struct Curl_handler Curl_handler_imap_proxy = { static const struct Curl_handler Curl_handler_imap_proxy = {
"IMAP", /* scheme */ "IMAP", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -188,7 +190,7 @@ static const struct Curl_handler Curl_handler_imap_proxy = {
static const struct Curl_handler Curl_handler_imaps_proxy = { static const struct Curl_handler Curl_handler_imaps_proxy = {
"IMAPS", /* scheme */ "IMAPS", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -268,7 +270,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
int *resp) int *resp)
{ {
struct IMAP *imap = conn->data->state.proto.imap; struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
const char *id = imapc->resptag; const char *id = imapc->resptag;
size_t id_len = strlen(id); size_t id_len = strlen(id);
@@ -307,7 +309,12 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
(strcmp(imap->custom, "STORE") || (strcmp(imap->custom, "STORE") ||
!imap_matchresp(line, len, "FETCH")) && !imap_matchresp(line, len, "FETCH")) &&
strcmp(imap->custom, "SELECT") && strcmp(imap->custom, "SELECT") &&
strcmp(imap->custom, "EXAMINE"))) strcmp(imap->custom, "EXAMINE") &&
strcmp(imap->custom, "SEARCH") &&
strcmp(imap->custom, "EXPUNGE") &&
strcmp(imap->custom, "LSUB") &&
strcmp(imap->custom, "UID") &&
strcmp(imap->custom, "NOOP")))
return FALSE; return FALSE;
break; break;
@@ -330,7 +337,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
return TRUE; return TRUE;
} }
/* Do we have a continuation response? */ /* Do we have a continuation response? This should be a + symbol followed by
a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
some e-mail servers ignore this and only send a single + instead. */
if((len == 3 && !memcmp("+", line, 1)) || if((len == 3 && !memcmp("+", line, 1)) ||
(len >= 2 && !memcmp("+ ", line, 2))) { (len >= 2 && !memcmp("+ ", line, 2))) {
switch(imapc->state) { switch(imapc->state) {
@@ -343,6 +353,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
case IMAP_AUTHENTICATE_DIGESTMD5_RESP: case IMAP_AUTHENTICATE_DIGESTMD5_RESP:
case IMAP_AUTHENTICATE_NTLM: case IMAP_AUTHENTICATE_NTLM:
case IMAP_AUTHENTICATE_NTLM_TYPE2MSG: case IMAP_AUTHENTICATE_NTLM_TYPE2MSG:
case IMAP_AUTHENTICATE_XOAUTH2:
case IMAP_AUTHENTICATE_FINAL: case IMAP_AUTHENTICATE_FINAL:
case IMAP_APPEND: case IMAP_APPEND:
*resp = '+'; *resp = '+';
@@ -360,6 +371,35 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE; /* Nothing for us */ return FALSE; /* Nothing for us */
} }
/***********************************************************************
*
* imap_get_message()
*
* Gets the authentication message from the response buffer.
*/
static void imap_get_message(char *buffer, char** outptr)
{
size_t len = 0;
char* message = NULL;
/* Find the start of the message */
for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
;
/* Find the end of the message */
for(len = strlen(message); len--;)
if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
message[len] != '\t')
break;
/* Terminate the message */
if(++len) {
message[len] = '\0';
}
*outptr = message;
}
/*********************************************************************** /***********************************************************************
* *
* state() * state()
@@ -385,6 +425,8 @@ static void state(struct connectdata *conn, imapstate newstate)
"AUTHENTICATE_DIGESTMD5_RESP", "AUTHENTICATE_DIGESTMD5_RESP",
"AUTHENTICATE_NTLM", "AUTHENTICATE_NTLM",
"AUTHENTICATE_NTLM_TYPE2MSG", "AUTHENTICATE_NTLM_TYPE2MSG",
"AUTHENTICATE_XOAUTH2",
"AUTHENTICATE_CANCEL",
"AUTHENTICATE_FINAL", "AUTHENTICATE_FINAL",
"LOGIN", "LOGIN",
"LIST", "LIST",
@@ -542,18 +584,18 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
return result; return result;
} }
/* Calculate the supported authentication mechanism by decreasing order of /* Calculate the supported authentication mechanism, by decreasing order of
security */ security, as well as the initial response where appropriate */
#ifndef CURL_DISABLE_CRYPTO_AUTH #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)) { (imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5"; mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = IMAP_AUTHENTICATE_DIGESTMD5; state1 = IMAP_AUTHENTICATE_DIGESTMD5;
imapc->authused = SASL_MECH_DIGEST_MD5; 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)) { (imapc->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5"; mech = SASL_MECH_STRING_CRAM_MD5;
state1 = IMAP_AUTHENTICATE_CRAMMD5; state1 = IMAP_AUTHENTICATE_CRAMMD5;
imapc->authused = SASL_MECH_CRAM_MD5; imapc->authused = SASL_MECH_CRAM_MD5;
} }
@@ -562,7 +604,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
#ifdef USE_NTLM #ifdef USE_NTLM
if((imapc->authmechs & SASL_MECH_NTLM) && if((imapc->authmechs & SASL_MECH_NTLM) &&
(imapc->prefmech & SASL_MECH_NTLM)) { (imapc->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM"; mech = SASL_MECH_STRING_NTLM;
state1 = IMAP_AUTHENTICATE_NTLM; state1 = IMAP_AUTHENTICATE_NTLM;
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG; state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
imapc->authused = SASL_MECH_NTLM; imapc->authused = SASL_MECH_NTLM;
@@ -574,9 +616,22 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
} }
else else
#endif #endif
if((imapc->authmechs & SASL_MECH_LOGIN) && if(((imapc->authmechs & SASL_MECH_XOAUTH2) &&
(imapc->prefmech & SASL_MECH_XOAUTH2) &&
(imapc->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
state1 = IMAP_AUTHENTICATE_XOAUTH2;
state2 = IMAP_AUTHENTICATE_FINAL;
imapc->authused = SASL_MECH_XOAUTH2;
if(imapc->ir_supported || data->set.sasl_ir)
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&initresp, &len);
}
else if((imapc->authmechs & SASL_MECH_LOGIN) &&
(imapc->prefmech & SASL_MECH_LOGIN)) { (imapc->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN"; mech = SASL_MECH_STRING_LOGIN;
state1 = IMAP_AUTHENTICATE_LOGIN; state1 = IMAP_AUTHENTICATE_LOGIN;
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD; state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
imapc->authused = SASL_MECH_LOGIN; imapc->authused = SASL_MECH_LOGIN;
@@ -587,7 +642,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
} }
else if((imapc->authmechs & SASL_MECH_PLAIN) && else if((imapc->authmechs & SASL_MECH_PLAIN) &&
(imapc->prefmech & SASL_MECH_PLAIN)) { (imapc->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN"; mech = SASL_MECH_STRING_PLAIN;
state1 = IMAP_AUTHENTICATE_PLAIN; state1 = IMAP_AUTHENTICATE_PLAIN;
state2 = IMAP_AUTHENTICATE_FINAL; state2 = IMAP_AUTHENTICATE_FINAL;
imapc->authused = SASL_MECH_PLAIN; imapc->authused = SASL_MECH_PLAIN;
@@ -598,7 +653,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
} }
if(!result) { if(!result) {
if(mech) { if(mech && (imapc->preftype & IMAP_TYPE_SASL)) {
/* Perform SASL based authentication */ /* Perform SASL based authentication */
if(initresp) { if(initresp) {
result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp); result = imap_sendf(conn, "AUTHENTICATE %s %s", mech, initresp);
@@ -615,7 +670,8 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
Curl_safefree(initresp); Curl_safefree(initresp);
} }
else if(!imapc->login_disabled) else if((!imapc->login_disabled) &&
(imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */ /* Perform clear text authentication */
result = imap_perform_login(conn); result = imap_perform_login(conn);
else { else {
@@ -638,7 +694,7 @@ static CURLcode imap_perform_list(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap = data->req.protop;
char *mailbox; char *mailbox;
if(imap->custom) if(imap->custom)
@@ -673,7 +729,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap = data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
char *mailbox; char *mailbox;
@@ -712,7 +768,7 @@ static CURLcode imap_perform_select(struct connectdata *conn)
static CURLcode imap_perform_fetch(struct connectdata *conn) static CURLcode imap_perform_fetch(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->state.proto.imap; struct IMAP *imap = conn->data->req.protop;
/* Check we have a UID */ /* Check we have a UID */
if(!imap->uid) { if(!imap->uid) {
@@ -740,7 +796,7 @@ static CURLcode imap_perform_fetch(struct connectdata *conn)
static CURLcode imap_perform_append(struct connectdata *conn) static CURLcode imap_perform_append(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct IMAP *imap = conn->data->state.proto.imap; struct IMAP *imap = conn->data->req.protop;
char *mailbox; char *mailbox;
/* Check we have a mailbox */ /* Check we have a mailbox */
@@ -864,20 +920,22 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
wordlen -= 5; wordlen -= 5;
/* Test the word for a matching authentication mechanism */ /* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
imapc->authmechs |= SASL_MECH_LOGIN; imapc->authmechs |= SASL_MECH_LOGIN;
if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
imapc->authmechs |= SASL_MECH_PLAIN; imapc->authmechs |= SASL_MECH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
imapc->authmechs |= SASL_MECH_CRAM_MD5; imapc->authmechs |= SASL_MECH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
imapc->authmechs |= SASL_MECH_DIGEST_MD5; imapc->authmechs |= SASL_MECH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
imapc->authmechs |= SASL_MECH_GSSAPI; imapc->authmechs |= SASL_MECH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
imapc->authmechs |= SASL_MECH_EXTERNAL; imapc->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
imapc->authmechs |= SASL_MECH_NTLM; imapc->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
imapc->authmechs |= SASL_MECH_XOAUTH2;
} }
line += wordlen; line += wordlen;
@@ -950,20 +1008,17 @@ static CURLcode imap_state_auth_plain_resp(struct connectdata *conn,
/* Create the authorisation message */ /* Create the authorisation message */
result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
&plainauth, &len); &plainauth, &len);
if(!result && plainauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth);
/* Send the message */ if(!result)
if(!result) { state(conn, IMAP_AUTHENTICATE_FINAL);
if(plainauth) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth);
if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL);
}
Curl_safefree(plainauth);
} }
} }
Curl_safefree(plainauth);
return result; return result;
} }
@@ -987,20 +1042,17 @@ static CURLcode imap_state_auth_login_resp(struct connectdata *conn,
/* Create the user message */ /* Create the user message */
result = Curl_sasl_create_login_message(data, conn->user, result = Curl_sasl_create_login_message(data, conn->user,
&authuser, &len); &authuser, &len);
if(!result && authuser) {
/* Send the user */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser);
/* Send the user */ if(!result)
if(!result) { state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD);
if(authuser) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser);
if(!result)
state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD);
}
Curl_safefree(authuser);
} }
} }
Curl_safefree(authuser);
return result; return result;
} }
@@ -1024,20 +1076,17 @@ static CURLcode imap_state_auth_login_password_resp(struct connectdata *conn,
/* Create the password message */ /* Create the password message */
result = Curl_sasl_create_login_message(data, conn->passwd, result = Curl_sasl_create_login_message(data, conn->passwd,
&authpasswd, &len); &authpasswd, &len);
if(!result && authpasswd) {
/* Send the password */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd);
/* Send the password */ if(!result)
if(!result) { state(conn, IMAP_AUTHENTICATE_FINAL);
if(authpasswd) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd);
if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL);
}
Curl_safefree(authpasswd);
} }
} }
Curl_safefree(authpasswd);
return result; return result;
} }
@@ -1049,9 +1098,10 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char *chlg64 = data->state.buffer; char *chlg = NULL;
size_t len = 0; char *chlg64 = NULL;
char *rplyb64 = NULL; char *rplyb64 = NULL;
size_t len = 0;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -1060,38 +1110,34 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
/* Get the challenge */ /* Get the challenge message */
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) imap_get_message(data->state.buffer, &chlg64);
;
/* Terminate the challenge */ /* Decode the challenge message */
if(*chlg64 != '=') { result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
for(len = strlen(chlg64); len--;) if(result) {
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' && /* Send the cancellation */
chlg64[len] != '\t') result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
break;
if(++len) { if(!result)
chlg64[len] = '\0'; state(conn, IMAP_AUTHENTICATE_CANCEL);
}
} }
else {
/* Create the response message */ /* Create the response message */
result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user, result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user,
conn->passwd, &rplyb64, &len); conn->passwd, &rplyb64, &len);
if(!result && rplyb64) {
/* Send the response */ /* Send the response */
if(!result) {
if(rplyb64) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
if(!result) if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL); state(conn, IMAP_AUTHENTICATE_FINAL);
} }
Curl_safefree(rplyb64);
} }
Curl_safefree(chlg);
Curl_safefree(rplyb64);
return result; return result;
} }
@@ -1102,9 +1148,13 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char *chlg64 = data->state.buffer; char *chlg64 = NULL;
size_t len = 0;
char *rplyb64 = NULL; char *rplyb64 = NULL;
size_t len = 0;
char nonce[64];
char realm[128];
char algorithm[64];
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -1113,27 +1163,36 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
/* Get the challenge */ /* Get the challenge message */
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) imap_get_message(data->state.buffer, &chlg64);
;
/* Create the response message */ /* Decode the challange message */
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user, result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
conn->passwd, "imap", realm, sizeof(realm),
&rplyb64, &len); algorithm, sizeof(algorithm));
if(result || strcmp(algorithm, "md5-sess") != 0) {
/* Send the cancellation */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
/* Send the response */ if(!result)
if(!result) { state(conn, IMAP_AUTHENTICATE_CANCEL);
if(rplyb64) { }
else {
/* Create the response message */
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
conn->user, conn->passwd,
"imap", &rplyb64, &len);
if(!result && rplyb64) {
/* Send the response */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64); result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
if(!result) if(!result)
state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP); state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP);
} }
Curl_safefree(rplyb64);
} }
Curl_safefree(rplyb64);
return result; return result;
} }
@@ -1185,20 +1244,17 @@ static CURLcode imap_state_auth_ntlm_resp(struct connectdata *conn,
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
&conn->ntlm, &conn->ntlm,
&type1msg, &len); &type1msg, &len);
if(!result && type1msg) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg);
/* Send the message */ if(!result)
if(!result) { state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG);
if(type1msg) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg);
if(!result)
state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG);
}
Curl_safefree(type1msg);
} }
} }
Curl_safefree(type1msg);
return result; return result;
} }
@@ -1209,8 +1265,9 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
size_t len = 0; char *type2msg = NULL;
char *type3msg = NULL; char *type3msg = NULL;
size_t len = 0;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -1219,31 +1276,90 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
} }
else { else {
/* Create the type-3 message */ /* Get the challenge message */
result = Curl_sasl_create_ntlm_type3_message(data, imap_get_message(data->state.buffer, &type2msg);
data->state.buffer + 2,
conn->user, conn->passwd,
&conn->ntlm,
&type3msg, &len);
/* Send the message */ /* Decode the type-2 message */
if(!result) { result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
if(type3msg) { if(result) {
/* Send the cancellation */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
if(!result)
state(conn, IMAP_AUTHENTICATE_CANCEL);
}
else {
/* Create the type-3 message */
result = Curl_sasl_create_ntlm_type3_message(data, conn->user,
conn->passwd, &conn->ntlm,
&type3msg, &len);
if(!result && type3msg) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg); result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg);
if(!result) if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL); state(conn, IMAP_AUTHENTICATE_FINAL);
} }
Curl_safefree(type3msg);
} }
} }
Curl_safefree(type3msg);
return result; return result;
} }
#endif #endif
/* For final responses to the AUTHENTICATE sequence */ /* For AUTHENTICATE XOAUTH2 (without initial response) responses */
static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *xoauth = NULL;
(void)instate; /* no use for this yet */
if(imapcode != '+') {
failf(data, "Access denied: %d", imapcode);
result = CURLE_LOGIN_DENIED;
}
else {
/* Create the authorisation message */
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&xoauth, &len);
if(!result && xoauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL);
}
}
Curl_safefree(xoauth);
return result;
}
/* For AUTHENTICATE cancellation responses */
static CURLcode imap_state_auth_cancel_resp(struct connectdata *conn,
int imapcode,
imapstate instate)
{
struct SessionHandle *data = conn->data;
(void)imapcode;
(void)instate; /* no use for this yet */
failf(data, "Authentication cancelled");
return CURLE_LOGIN_DENIED;
}
/* For final responses in the AUTHENTICATE sequence */
static CURLcode imap_state_auth_final_resp(struct connectdata *conn, static CURLcode imap_state_auth_final_resp(struct connectdata *conn,
int imapcode, int imapcode,
imapstate instate) imapstate instate)
@@ -1316,7 +1432,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = conn->data->state.proto.imap; struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer; const char *line = data->state.buffer;
char tmp[20]; char tmp[20];
@@ -1407,10 +1523,10 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
return result; return result;
data->req.bytecount += chunk; data->req.bytecount += chunk;
size -= chunk;
infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU infof(data, "Written %" FORMAT_OFF_TU " bytes, %" FORMAT_OFF_TU
" bytes are left for transfer\n", (curl_off_t)chunk, size); " bytes are left for transfer\n", (curl_off_t)chunk,
size - chunk);
/* Have we used the entire cache or just part of it?*/ /* Have we used the entire cache or just part of it?*/
if(pp->cache_size > chunk) { if(pp->cache_size > chunk) {
@@ -1427,7 +1543,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
} }
} }
if(!size) if(data->req.bytecount == size)
/* The entire data is already transferred! */ /* The entire data is already transferred! */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
else { else {
@@ -1592,6 +1708,14 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
break; break;
#endif #endif
case IMAP_AUTHENTICATE_XOAUTH2:
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
break;
case IMAP_AUTHENTICATE_CANCEL:
result = imap_state_auth_cancel_resp(conn, imapcode, imapc->state);
break;
case IMAP_AUTHENTICATE_FINAL: case IMAP_AUTHENTICATE_FINAL:
result = imap_state_auth_final_resp(conn, imapcode, imapc->state); result = imap_state_auth_final_resp(conn, imapcode, imapc->state);
break; break;
@@ -1642,11 +1766,13 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone);
else if(result || !imapc->ssldone)
result = Curl_pp_statemach(&imapc->pp, FALSE); return result;
}
result = Curl_pp_statemach(&imapc->pp, FALSE);
*done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
return result; return result;
@@ -1669,13 +1795,11 @@ static CURLcode imap_init(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap;
if(!imap) { imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
imap = data->state.proto.imap = calloc(sizeof(struct IMAP), 1); if(!imap)
if(!imap) result = CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
}
return result; return result;
} }
@@ -1705,15 +1829,6 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
*done = FALSE; /* default to not done yet */ *done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
/* Initialise the IMAP layer */
result = imap_init(conn);
if(result)
return result;
/* We always support persistent connections in IMAP */ /* We always support persistent connections in IMAP */
conn->bits.close = FALSE; conn->bits.close = FALSE;
@@ -1723,7 +1838,8 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
pp->endofresp = imap_endofresp; pp->endofresp = imap_endofresp;
pp->conn = conn; pp->conn = conn;
/* Set the default preferred authentication mechanism */ /* Set the default preferred authentication type and mechanism */
imapc->preftype = IMAP_TYPE_ANY;
imapc->prefmech = SASL_AUTH_ANY; imapc->prefmech = SASL_AUTH_ANY;
/* Initialise the pingpong layer */ /* Initialise the pingpong layer */
@@ -1759,7 +1875,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap = data->req.protop;
(void)premature; (void)premature;
@@ -1824,7 +1940,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
/* This is IMAP and no proxy */ /* This is IMAP and no proxy */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap = data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc; struct imap_conn *imapc = &conn->proto.imapc;
bool selected = FALSE; bool selected = FALSE;
@@ -1891,15 +2007,6 @@ static CURLcode imap_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
/* Since connections can be re-used between SessionHandles, there might be a
connection already existing but on a fresh SessionHandle struct. As such
we make sure we have a good IMAP struct to play with. For new connections
the IMAP struct is allocated and setup in the imap_connect() function. */
Curl_reset_reqproto(conn);
result = imap_init(conn);
if(result)
return result;
/* Parse the URL path */ /* Parse the URL path */
result = imap_parse_url_path(conn); result = imap_parse_url_path(conn);
if(result) if(result)
@@ -1932,7 +2039,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
/* The IMAP session may or may not have been allocated/setup at this /* The IMAP session may or may not have been allocated/setup at this
point! */ point! */
if(!dead_connection && imapc->pp.conn) if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
if(!imap_perform_logout(conn)) if(!imap_perform_logout(conn))
(void)imap_block_statemach(conn); /* ignore errors on LOGOUT */ (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
@@ -1952,7 +2059,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
/* Call this when the DO phase has completed */ /* Call this when the DO phase has completed */
static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
{ {
struct IMAP *imap = conn->data->state.proto.imap; struct IMAP *imap = conn->data->req.protop;
(void)connected; (void)connected;
@@ -2018,6 +2125,11 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
/* Initialise the IMAP layer */
CURLcode result = imap_init(conn);
if(result)
return result;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel IMAP operations through the proxy, we /* Unless we have asked to tunnel IMAP operations through the proxy, we
switch and use HTTP operations only */ switch and use HTTP operations only */
@@ -2033,10 +2145,8 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
#endif #endif
} }
/* We explicitly mark this connection as persistent here as we're doing /* set it up as an HTTP connection instead */
IMAP over HTTP and thus we accidentally avoid setting this value return conn->handler->setup_connection(conn);
otherwise */
conn->bits.close = FALSE;
#else #else
failf(data, "IMAP over http proxy requires HTTP support built-in!"); failf(data, "IMAP over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL; return CURLE_UNSUPPORTED_PROTOCOL;
@@ -2223,22 +2333,42 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
if(strnequal(key, "AUTH", 4)) { if(strnequal(key, "AUTH", 4)) {
const char *value = ptr + 1; const char *value = ptr + 1;
if(strequal(value, "*")) if(strequal(value, "*")) {
imapc->preftype = IMAP_TYPE_ANY;
imapc->prefmech = SASL_AUTH_ANY; imapc->prefmech = SASL_AUTH_ANY;
else if(strequal(value, "LOGIN")) }
else if(strequal(value, SASL_MECH_STRING_LOGIN)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_LOGIN; imapc->prefmech = SASL_MECH_LOGIN;
else if(strequal(value, "PLAIN")) }
else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_PLAIN; imapc->prefmech = SASL_MECH_PLAIN;
else if(strequal(value, "CRAM-MD5")) }
else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_CRAM_MD5; imapc->prefmech = SASL_MECH_CRAM_MD5;
else if(strequal(value, "DIGEST-MD5")) }
else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_DIGEST_MD5; imapc->prefmech = SASL_MECH_DIGEST_MD5;
else if(strequal(value, "GSSAPI")) }
else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_GSSAPI; imapc->prefmech = SASL_MECH_GSSAPI;
else if(strequal(value, "NTLM")) }
else if(strequal(value, SASL_MECH_STRING_NTLM)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_NTLM; imapc->prefmech = SASL_MECH_NTLM;
else }
else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_XOAUTH2;
}
else {
imapc->preftype = IMAP_TYPE_NONE;
imapc->prefmech = SASL_AUTH_NONE; imapc->prefmech = SASL_AUTH_NONE;
}
} }
else else
result = CURLE_URL_MALFORMAT; result = CURLE_URL_MALFORMAT;
@@ -2259,7 +2389,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
/* The imap struct is already initialised in imap_connect() */ /* The imap struct is already initialised in imap_connect() */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap = data->req.protop;
const char *begin = data->state.path; const char *begin = data->state.path;
const char *ptr = begin; const char *ptr = begin;
@@ -2367,7 +2497,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct IMAP *imap = data->state.proto.imap; struct IMAP *imap = data->req.protop;
const char *custom = data->set.str[STRING_CUSTOMREQUEST]; const char *custom = data->set.str[STRING_CUSTOMREQUEST];
if(custom) { if(custom) {

View File

@@ -43,6 +43,8 @@ typedef enum {
IMAP_AUTHENTICATE_DIGESTMD5_RESP, IMAP_AUTHENTICATE_DIGESTMD5_RESP,
IMAP_AUTHENTICATE_NTLM, IMAP_AUTHENTICATE_NTLM,
IMAP_AUTHENTICATE_NTLM_TYPE2MSG, IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
IMAP_AUTHENTICATE_XOAUTH2,
IMAP_AUTHENTICATE_CANCEL,
IMAP_AUTHENTICATE_FINAL, IMAP_AUTHENTICATE_FINAL,
IMAP_LOGIN, IMAP_LOGIN,
IMAP_LIST, IMAP_LIST,
@@ -76,6 +78,7 @@ struct imap_conn {
imapstate state; /* Always use imap.c:state() to change state! */ imapstate state; /* Always use imap.c:state() to change state! */
bool ssldone; /* Is connect() over SSL done? */ bool ssldone; /* Is connect() over SSL done? */
unsigned int authmechs; /* Accepted authentication mechanisms */ unsigned int authmechs; /* Accepted authentication mechanisms */
unsigned int preftype; /* Preferred authentication type */
unsigned int prefmech; /* Preferred authentication mechanism */ unsigned int prefmech; /* Preferred authentication mechanism */
unsigned int authused; /* Auth mechanism used for the connection */ unsigned int authused; /* Auth mechanism used for the connection */
int cmdid; /* Last used command ID */ int cmdid; /* Last used command ID */
@@ -90,4 +93,12 @@ struct imap_conn {
extern const struct Curl_handler Curl_handler_imap; extern const struct Curl_handler Curl_handler_imap;
extern const struct Curl_handler Curl_handler_imaps; extern const struct Curl_handler Curl_handler_imaps;
/* Authentication type flags */
#define IMAP_TYPE_CLEARTEXT (1 << 0)
#define IMAP_TYPE_SASL (1 << 1)
/* Authentication type values */
#define IMAP_TYPE_NONE 0
#define IMAP_TYPE_ANY ~0U
#endif /* HEADER_CURL_IMAP_H */ #endif /* HEADER_CURL_IMAP_H */

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

198
lib/nss.c
View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -63,6 +63,7 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "rawstr.h" #include "rawstr.h"
#include "warnless.h" #include "warnless.h"
#include "x509asn1.h"
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #include "memdebug.h"
@@ -76,9 +77,7 @@ PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
PRLock * nss_initlock = NULL; PRLock * nss_initlock = NULL;
PRLock * nss_crllock = NULL; PRLock * nss_crllock = NULL;
#ifdef HAVE_NSS_INITCONTEXT
NSSInitContext * nss_context = NULL; NSSInitContext * nss_context = NULL;
#endif
volatile int initialized = 0; volatile int initialized = 0;
@@ -653,6 +652,10 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
SSLChannelInfo channel; SSLChannelInfo channel;
SSLCipherSuiteInfo suite; SSLCipherSuiteInfo suite;
CERTCertificate *cert; CERTCertificate *cert;
CERTCertificate *cert2;
CERTCertificate *cert3;
PRTime now;
int i;
if(SSL_GetChannelInfo(sock, &channel, sizeof channel) == if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
SECSuccess && channel.length == sizeof channel && SECSuccess && channel.length == sizeof channel &&
@@ -663,11 +666,45 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
} }
} }
infof(conn->data, "Server certificate:\n");
cert = SSL_PeerCertificate(sock); cert = SSL_PeerCertificate(sock);
display_cert_info(conn->data, cert);
CERT_DestroyCertificate(cert); if(cert) {
infof(conn->data, "Server certificate:\n");
if(!conn->data->set.ssl.certinfo) {
display_cert_info(conn->data, cert);
CERT_DestroyCertificate(cert);
}
else {
/* Count certificates in chain. */
now = PR_Now();
i = 1;
if(!cert->isRoot) {
cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
while(cert2) {
i++;
if(cert2->isRoot) {
CERT_DestroyCertificate(cert2);
break;
}
cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
CERT_DestroyCertificate(cert2);
cert2 = cert3;
}
}
Curl_ssl_init_certinfo(conn->data, i);
for(i = 0; cert; cert = cert2) {
Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
(char *)cert->derCert.data + cert->derCert.len);
if(cert->isRoot) {
CERT_DestroyCertificate(cert);
break;
}
cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
CERT_DestroyCertificate(cert);
}
}
}
return; return;
} }
@@ -854,7 +891,6 @@ isTLSIntoleranceError(PRInt32 err)
static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
{ {
#ifdef HAVE_NSS_INITCONTEXT
NSSInitParameters initparams; NSSInitParameters initparams;
if(nss_context != NULL) if(nss_context != NULL)
@@ -862,12 +898,6 @@ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
memset((void *) &initparams, '\0', sizeof(initparams)); memset((void *) &initparams, '\0', sizeof(initparams));
initparams.length = sizeof(initparams); initparams.length = sizeof(initparams);
#else /* HAVE_NSS_INITCONTEXT */
SECStatus rv;
if(NSS_IsInitialized())
return CURLE_OK;
#endif
if(cert_dir) { if(cert_dir) {
const bool use_sql = NSS_VersionCheck("3.12.0"); const bool use_sql = NSS_VersionCheck("3.12.0");
@@ -876,35 +906,22 @@ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
infof(data, "Initializing NSS with certpath: %s\n", certpath); infof(data, "Initializing NSS with certpath: %s\n", certpath);
#ifdef HAVE_NSS_INITCONTEXT
nss_context = NSS_InitContext(certpath, "", "", "", &initparams, nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
free(certpath); free(certpath);
if(nss_context != NULL) if(nss_context != NULL)
return CURLE_OK; return CURLE_OK;
#else /* HAVE_NSS_INITCONTEXT */
rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
free(certpath);
if(rv == SECSuccess)
return CURLE_OK;
#endif
infof(data, "Unable to initialize NSS database\n"); infof(data, "Unable to initialize NSS database\n");
} }
infof(data, "Initializing NSS with certpath: none\n"); infof(data, "Initializing NSS with certpath: none\n");
#ifdef HAVE_NSS_INITCONTEXT
nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
| NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
| NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
if(nss_context != NULL) if(nss_context != NULL)
return CURLE_OK; return CURLE_OK;
#else /* HAVE_NSS_INITCONTEXT */
if(NSS_NoDB_Init(NULL) == SECSuccess)
return CURLE_OK;
#endif
infof(data, "Unable to initialize NSS\n"); infof(data, "Unable to initialize NSS\n");
return CURLE_SSL_CACERT_BADFILE; return CURLE_SSL_CACERT_BADFILE;
@@ -1000,12 +1017,8 @@ void Curl_nss_cleanup(void)
SECMOD_DestroyModule(mod); SECMOD_DestroyModule(mod);
mod = NULL; mod = NULL;
} }
#ifdef HAVE_NSS_INITCONTEXT
NSS_ShutdownContext(nss_context); NSS_ShutdownContext(nss_context);
nss_context = NULL; nss_context = NULL;
#else /* HAVE_NSS_INITCONTEXT */
NSS_Shutdown();
#endif
} }
PR_Unlock(nss_initlock); PR_Unlock(nss_initlock);
@@ -1172,13 +1185,69 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
static CURLcode nss_init_sslver(SSLVersionRange *sslver,
struct SessionHandle *data)
{
switch (data->set.ssl.version) {
default:
case CURL_SSLVERSION_DEFAULT:
if(data->state.ssl_connect_retry) {
infof(data, "TLS disabled due to previous handshake failure\n");
sslver->max = SSL_LIBRARY_VERSION_3_0;
}
return CURLE_OK;
case CURL_SSLVERSION_TLSv1:
sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
#elif defined SSL_LIBRARY_VERSION_TLS_1_1
sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
#else
sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
#endif
return CURLE_OK;
case CURL_SSLVERSION_SSLv2:
sslver->min = SSL_LIBRARY_VERSION_2;
sslver->max = SSL_LIBRARY_VERSION_2;
return CURLE_OK;
case CURL_SSLVERSION_SSLv3:
sslver->min = SSL_LIBRARY_VERSION_3_0;
sslver->max = SSL_LIBRARY_VERSION_3_0;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_0:
sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
sslver->max = SSL_LIBRARY_VERSION_TLS_1_0;
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_1:
#ifdef SSL_LIBRARY_VERSION_TLS_1_1
sslver->min = SSL_LIBRARY_VERSION_TLS_1_1;
sslver->max = SSL_LIBRARY_VERSION_TLS_1_1;
return CURLE_OK;
#endif
break;
case CURL_SSLVERSION_TLSv1_2:
#ifdef SSL_LIBRARY_VERSION_TLS_1_2
sslver->min = SSL_LIBRARY_VERSION_TLS_1_2;
sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
return CURLE_OK;
#endif
break;
}
failf(data, "TLS minor version cannot be set");
return CURLE_SSL_CONNECT_ERROR;
}
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{ {
PRErrorCode err = 0; PRErrorCode err = 0;
PRFileDesc *model = NULL; PRFileDesc *model = NULL;
PRBool ssl2 = PR_FALSE;
PRBool ssl3 = PR_FALSE;
PRBool tlsv1 = PR_FALSE;
PRBool ssl_no_cache; PRBool ssl_no_cache;
PRBool ssl_cbc_random_iv; PRBool ssl_cbc_random_iv;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
@@ -1190,6 +1259,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
long time_left; long time_left;
PRUint32 timeout; PRUint32 timeout;
SSLVersionRange sslver = {
SSL_LIBRARY_VERSION_3_0, /* min */
SSL_LIBRARY_VERSION_TLS_1_0 /* max */
};
if(connssl->state == ssl_connection_complete) if(connssl->state == ssl_connection_complete)
return CURLE_OK; return CURLE_OK;
@@ -1244,39 +1318,16 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
goto error; goto error;
/* do not use SSL cache if we are not going to verify peer */ /* do not use SSL cache if disabled or we are not going to verify peer */
ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE; ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
PR_FALSE : PR_TRUE;
if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
goto error; goto error;
switch (data->set.ssl.version) { /* enable/disable the requested SSL version(s) */
default: if(nss_init_sslver(&sslver, data) != CURLE_OK)
case CURL_SSLVERSION_DEFAULT:
ssl3 = PR_TRUE;
if(data->state.ssl_connect_retry)
infof(data, "TLS disabled due to previous handshake failure\n");
else
tlsv1 = PR_TRUE;
break;
case CURL_SSLVERSION_TLSv1:
tlsv1 = PR_TRUE;
break;
case CURL_SSLVERSION_SSLv2:
ssl2 = PR_TRUE;
break;
case CURL_SSLVERSION_SSLv3:
ssl3 = PR_TRUE;
break;
}
if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
goto error; goto error;
if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess) if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
goto error;
if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
goto error;
if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
goto error; goto error;
ssl_cbc_random_iv = !data->set.ssl_enable_beast; ssl_cbc_random_iv = !data->set.ssl_enable_beast;
@@ -1462,11 +1513,13 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
if(model) if(model)
PR_Close(model); PR_Close(model);
/* cleanup on connection failure */ /* cleanup on connection failure */
Curl_llist_destroy(connssl->obj_list, NULL); Curl_llist_destroy(connssl->obj_list, NULL);
connssl->obj_list = NULL; connssl->obj_list = NULL;
if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) { if((sslver.min == SSL_LIBRARY_VERSION_3_0)
&& (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0)
&& isTLSIntoleranceError(err)) {
/* schedule reconnect through Curl_retry_request() */ /* schedule reconnect through Curl_retry_request() */
data->state.ssl_connect_retry = TRUE; data->state.ssl_connect_retry = TRUE;
infof(data, "Error in TLS handshake, trying SSLv3...\n"); infof(data, "Error in TLS handshake, trying SSLv3...\n");
@@ -1543,9 +1596,8 @@ size_t Curl_nss_version(char *buffer, size_t size)
int Curl_nss_seed(struct SessionHandle *data) int Curl_nss_seed(struct SessionHandle *data)
{ {
/* TODO: implement? */ /* make sure that NSS is initialized */
(void) data; return !!Curl_nss_force_init(data);
return 0;
} }
void Curl_nss_random(struct SessionHandle *data, void Curl_nss_random(struct SessionHandle *data,
@@ -1553,7 +1605,11 @@ void Curl_nss_random(struct SessionHandle *data,
size_t length) size_t length)
{ {
Curl_nss_seed(data); /* Initiate the seed if not already done */ Curl_nss_seed(data); /* Initiate the seed if not already done */
PK11_GenerateRandom(entropy, curlx_uztosi(length)); if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) {
/* no way to signal a failure from here, we have to abort */
failf(data, "PK11_GenerateRandom() failed, calling abort()...");
abort();
}
} }
void Curl_nss_md5sum(unsigned char *tmp, /* input */ void Curl_nss_md5sum(unsigned char *tmp, /* input */

View File

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

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 * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@@ -526,7 +526,7 @@ static int parsedate(const char *date, time_t *output)
/* Add the time zone diff between local time zone and GMT. */ /* Add the time zone diff between local time zone and GMT. */
long delta = (long)(tzoff!=-1?tzoff:0); long delta = (long)(tzoff!=-1?tzoff:0);
if((delta>0) && (t + delta < t)) if((delta>0) && (t > LONG_MAX - delta))
return -1; /* time_t overflow */ return -1; /* time_t overflow */
t += delta; t += delta;

View File

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

View File

@@ -28,6 +28,8 @@
* RFC4422 Simple Authentication and Security Layer (SASL) * RFC4422 Simple Authentication and Security Layer (SASL)
* RFC4616 PLAIN authentication * RFC4616 PLAIN authentication
* RFC5034 POP3 SASL Authentication Mechanism * RFC5034 POP3 SASL Authentication Mechanism
* RFC6749 OAuth 2.0 Authorization Framework
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -163,7 +165,7 @@ const struct Curl_handler Curl_handler_pop3s = {
static const struct Curl_handler Curl_handler_pop3_proxy = { static const struct Curl_handler Curl_handler_pop3_proxy = {
"POP3", /* scheme */ "POP3", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -188,7 +190,7 @@ static const struct Curl_handler Curl_handler_pop3_proxy = {
static const struct Curl_handler Curl_handler_pop3s_proxy = { static const struct Curl_handler Curl_handler_pop3s_proxy = {
"POP3S", /* scheme */ "POP3S", /* scheme */
ZERO_NULL, /* setup_connection */ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */ Curl_http, /* do_it */
Curl_http_done, /* done */ Curl_http_done, /* done */
ZERO_NULL, /* do_more */ ZERO_NULL, /* do_more */
@@ -312,20 +314,22 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
wordlen++; wordlen++;
/* Test the word for a matching authentication mechanism */ /* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
pop3c->authmechs |= SASL_MECH_LOGIN; pop3c->authmechs |= SASL_MECH_LOGIN;
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
pop3c->authmechs |= SASL_MECH_PLAIN; pop3c->authmechs |= SASL_MECH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
pop3c->authmechs |= SASL_MECH_CRAM_MD5; pop3c->authmechs |= SASL_MECH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
pop3c->authmechs |= SASL_MECH_DIGEST_MD5; pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
pop3c->authmechs |= SASL_MECH_GSSAPI; pop3c->authmechs |= SASL_MECH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
pop3c->authmechs |= SASL_MECH_EXTERNAL; pop3c->authmechs |= SASL_MECH_EXTERNAL;
else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
pop3c->authmechs |= SASL_MECH_NTLM; pop3c->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
pop3c->authmechs |= SASL_MECH_XOAUTH2;
line += wordlen; line += wordlen;
len -= wordlen; len -= wordlen;
@@ -346,6 +350,35 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
return FALSE; /* Nothing for us */ return FALSE; /* Nothing for us */
} }
/***********************************************************************
*
* pop3_get_message()
*
* Gets the authentication message from the response buffer.
*/
static void pop3_get_message(char *buffer, char** outptr)
{
size_t len = 0;
char* message = NULL;
/* Find the start of the message */
for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
;
/* Find the end of the message */
for(len = strlen(message); len--;)
if(message[len] != '\r' && message[len] != '\n' && message[len] != ' ' &&
message[len] != '\t')
break;
/* Terminate the message */
if(++len) {
message[len] = '\0';
}
*outptr = message;
}
/*********************************************************************** /***********************************************************************
* *
* state() * state()
@@ -371,6 +404,8 @@ static void state(struct connectdata *conn, pop3state newstate)
"AUTH_DIGESTMD5_RESP", "AUTH_DIGESTMD5_RESP",
"AUTH_NTLM", "AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG", "AUTH_NTLM_TYPE2MSG",
"AUTH_XOAUTH2",
"AUTH_CANCEL",
"AUTH_FINAL", "AUTH_FINAL",
"APOP", "APOP",
"USER", "USER",
@@ -566,19 +601,19 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
return result; return result;
} }
/* Calculate the supported authentication mechanism by decreasing order of /* Calculate the supported authentication mechanism, by decreasing order of
security */ security, as well as the initial response where appropriate */
if(pop3c->authtypes & POP3_TYPE_SASL) { if(pop3c->authtypes & POP3_TYPE_SASL) {
#ifndef CURL_DISABLE_CRYPTO_AUTH #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)) { (pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
mech = "DIGEST-MD5"; mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = POP3_AUTH_DIGESTMD5; state1 = POP3_AUTH_DIGESTMD5;
pop3c->authused = SASL_MECH_DIGEST_MD5; 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)) { (pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
mech = "CRAM-MD5"; mech = SASL_MECH_STRING_CRAM_MD5;
state1 = POP3_AUTH_CRAMMD5; state1 = POP3_AUTH_CRAMMD5;
pop3c->authused = SASL_MECH_CRAM_MD5; pop3c->authused = SASL_MECH_CRAM_MD5;
} }
@@ -587,7 +622,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
#ifdef USE_NTLM #ifdef USE_NTLM
if((pop3c->authmechs & SASL_MECH_NTLM) && if((pop3c->authmechs & SASL_MECH_NTLM) &&
(pop3c->prefmech & SASL_MECH_NTLM)) { (pop3c->prefmech & SASL_MECH_NTLM)) {
mech = "NTLM"; mech = SASL_MECH_STRING_NTLM;
state1 = POP3_AUTH_NTLM; state1 = POP3_AUTH_NTLM;
state2 = POP3_AUTH_NTLM_TYPE2MSG; state2 = POP3_AUTH_NTLM_TYPE2MSG;
pop3c->authused = SASL_MECH_NTLM; pop3c->authused = SASL_MECH_NTLM;
@@ -599,9 +634,22 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
} }
else else
#endif #endif
if((pop3c->authmechs & SASL_MECH_LOGIN) && if(((pop3c->authmechs & SASL_MECH_XOAUTH2) &&
(pop3c->prefmech & SASL_MECH_XOAUTH2) &&
(pop3c->prefmech != SASL_AUTH_ANY)) || conn->xoauth2_bearer) {
mech = SASL_MECH_STRING_XOAUTH2;
state1 = POP3_AUTH_XOAUTH2;
state2 = POP3_AUTH_FINAL;
pop3c->authused = SASL_MECH_XOAUTH2;
if(data->set.sasl_ir)
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&initresp, &len);
}
else if((pop3c->authmechs & SASL_MECH_LOGIN) &&
(pop3c->prefmech & SASL_MECH_LOGIN)) { (pop3c->prefmech & SASL_MECH_LOGIN)) {
mech = "LOGIN"; mech = SASL_MECH_STRING_LOGIN;
state1 = POP3_AUTH_LOGIN; state1 = POP3_AUTH_LOGIN;
state2 = POP3_AUTH_LOGIN_PASSWD; state2 = POP3_AUTH_LOGIN_PASSWD;
pop3c->authused = SASL_MECH_LOGIN; pop3c->authused = SASL_MECH_LOGIN;
@@ -612,7 +660,7 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
} }
else if((pop3c->authmechs & SASL_MECH_PLAIN) && else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
(pop3c->prefmech & SASL_MECH_PLAIN)) { (pop3c->prefmech & SASL_MECH_PLAIN)) {
mech = "PLAIN"; mech = SASL_MECH_STRING_PLAIN;
state1 = POP3_AUTH_PLAIN; state1 = POP3_AUTH_PLAIN;
state2 = POP3_AUTH_FINAL; state2 = POP3_AUTH_FINAL;
pop3c->authused = SASL_MECH_PLAIN; pop3c->authused = SASL_MECH_PLAIN;
@@ -673,7 +721,7 @@ static CURLcode pop3_perform_command(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3; struct POP3 *pop3 = data->req.protop;
const char *command = NULL; const char *command = NULL;
/* Calculate the default command */ /* Calculate the default command */
@@ -817,20 +865,17 @@ static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
/* Create the authorisation message */ /* Create the authorisation message */
result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd, result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
&plainauth, &len); &plainauth, &len);
if(!result && plainauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", plainauth);
/* Send the message */ if(!result)
if(!result) { state(conn, POP3_AUTH_FINAL);
if(plainauth) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", plainauth);
if(!result)
state(conn, POP3_AUTH_FINAL);
}
Curl_safefree(plainauth);
} }
} }
Curl_safefree(plainauth);
return result; return result;
} }
@@ -854,20 +899,17 @@ static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
/* Create the user message */ /* Create the user message */
result = Curl_sasl_create_login_message(data, conn->user, result = Curl_sasl_create_login_message(data, conn->user,
&authuser, &len); &authuser, &len);
if(!result && authuser) {
/* Send the user */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authuser);
/* Send the user */ if(!result)
if(!result) { state(conn, POP3_AUTH_LOGIN_PASSWD);
if(authuser) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authuser);
if(!result)
state(conn, POP3_AUTH_LOGIN_PASSWD);
}
Curl_safefree(authuser);
} }
} }
Curl_safefree(authuser);
return result; return result;
} }
@@ -891,20 +933,17 @@ static CURLcode pop3_state_auth_login_password_resp(struct connectdata *conn,
/* Create the password message */ /* Create the password message */
result = Curl_sasl_create_login_message(data, conn->passwd, result = Curl_sasl_create_login_message(data, conn->passwd,
&authpasswd, &len); &authpasswd, &len);
if(!result && authpasswd) {
/* Send the password */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authpasswd);
/* Send the password */ if(!result)
if(!result) { state(conn, POP3_AUTH_FINAL);
if(authpasswd) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authpasswd);
if(!result)
state(conn, POP3_AUTH_FINAL);
}
Curl_safefree(authpasswd);
} }
} }
Curl_safefree(authpasswd);
return result; return result;
} }
@@ -916,9 +955,10 @@ static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char *chlg64 = data->state.buffer; char *chlg = NULL;
size_t len = 0; char *chlg64 = NULL;
char *rplyb64 = NULL; char *rplyb64 = NULL;
size_t len = 0;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -927,38 +967,34 @@ static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
/* Get the challenge */ /* Get the challenge message */
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) pop3_get_message(data->state.buffer, &chlg64);
;
/* Terminate the challenge */ /* Decode the challenge message */
if(*chlg64 != '=') { result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
for(len = strlen(chlg64); len--;) if(result) {
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' && /* Send the cancellation */
chlg64[len] != '\t') result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
break;
if(++len) { if(!result)
chlg64[len] = '\0'; state(conn, POP3_AUTH_CANCEL);
}
} }
else {
/* Create the response message */ /* Create the response message */
result = Curl_sasl_create_cram_md5_message(data, chlg64, conn->user, result = Curl_sasl_create_cram_md5_message(data, chlg, conn->user,
conn->passwd, &rplyb64, &len); conn->passwd, &rplyb64, &len);
if(!result && rplyb64) {
/* Send the response */ /* Send the response */
if(!result) {
if(rplyb64) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64); result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
if(!result) if(!result)
state(conn, POP3_AUTH_FINAL); state(conn, POP3_AUTH_FINAL);
} }
Curl_safefree(rplyb64);
} }
Curl_safefree(chlg);
Curl_safefree(rplyb64);
return result; return result;
} }
@@ -969,9 +1005,13 @@ static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char *chlg64 = data->state.buffer; char *chlg64 = NULL;
size_t len = 0;
char *rplyb64 = NULL; char *rplyb64 = NULL;
size_t len = 0;
char nonce[64];
char realm[128];
char algorithm[64];
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -980,27 +1020,36 @@ static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
/* Get the challenge */ /* Get the challenge message */
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) pop3_get_message(data->state.buffer, &chlg64);
;
/* Create the response message */ /* Decode the challange message */
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user, result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
conn->passwd, "pop", realm, sizeof(realm),
&rplyb64, &len); algorithm, sizeof(algorithm));
if(result || strcmp(algorithm, "md5-sess") != 0) {
/* Send the cancellation */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
/* Send the response */ if(!result)
if(!result) { state(conn, POP3_AUTH_CANCEL);
if(rplyb64) { }
else {
/* Create the response message */
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
conn->user, conn->passwd,
"pop", &rplyb64, &len);
if(!result && rplyb64) {
/* Send the response */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64); result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
if(!result) if(!result)
state(conn, POP3_AUTH_DIGESTMD5_RESP); state(conn, POP3_AUTH_DIGESTMD5_RESP);
} }
Curl_safefree(rplyb64);
} }
Curl_safefree(rplyb64);
return result; return result;
} }
@@ -1052,20 +1101,17 @@ static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd, result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
&conn->ntlm, &conn->ntlm,
&type1msg, &len); &type1msg, &len);
if(!result && type1msg) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type1msg);
/* Send the message */ if(!result)
if(!result) { state(conn, POP3_AUTH_NTLM_TYPE2MSG);
if(type1msg) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type1msg);
if(!result)
state(conn, POP3_AUTH_NTLM_TYPE2MSG);
}
Curl_safefree(type1msg);
} }
} }
Curl_safefree(type1msg);
return result; return result;
} }
@@ -1076,8 +1122,9 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
size_t len = 0; char *type2msg = NULL;
char *type3msg = NULL; char *type3msg = NULL;
size_t len = 0;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
@@ -1086,31 +1133,89 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED; result = CURLE_LOGIN_DENIED;
} }
else { else {
/* Create the type-3 message */ /* Get the type-2 message */
result = Curl_sasl_create_ntlm_type3_message(data, pop3_get_message(data->state.buffer, &type2msg);
data->state.buffer + 2,
conn->user, conn->passwd,
&conn->ntlm,
&type3msg, &len);
/* Send the message */ /* Decode the type-2 message */
if(!result) { result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
if(type3msg) { if(result) {
/* Send the cancellation */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
if(!result)
state(conn, POP3_AUTH_CANCEL);
}
else {
/* Create the type-3 message */
result = Curl_sasl_create_ntlm_type3_message(data, conn->user,
conn->passwd, &conn->ntlm,
&type3msg, &len);
if(!result && type3msg) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type3msg); result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type3msg);
if(!result) if(!result)
state(conn, POP3_AUTH_FINAL); state(conn, POP3_AUTH_FINAL);
} }
Curl_safefree(type3msg);
} }
} }
Curl_safefree(type3msg);
return result; return result;
} }
#endif #endif
/* For final responses to the AUTH sequence */ /* For AUTH XOAUTH2 (without initial response) responses */
static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
int pop3code, pop3state instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t len = 0;
char *xoauth = NULL;
(void)instate; /* no use for this yet */
if(pop3code != '+') {
failf(data, "Access denied: %d", pop3code);
result = CURLE_LOGIN_DENIED;
}
else {
/* Create the authorisation message */
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer,
&xoauth, &len);
if(!result && xoauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
if(!result)
state(conn, POP3_AUTH_FINAL);
}
}
Curl_safefree(xoauth);
return result;
}
/* For AUTH cancellation responses */
static CURLcode pop3_state_auth_cancel_resp(struct connectdata *conn,
int pop3code,
pop3state instate)
{
struct SessionHandle *data = conn->data;
(void)pop3code;
(void)instate; /* no use for this yet */
failf(data, "Authentication cancelled");
return CURLE_LOGIN_DENIED;
}
/* For final responses in the AUTH sequence */
static CURLcode pop3_state_auth_final_resp(struct connectdata *conn, static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
int pop3code, int pop3code,
pop3state instate) pop3state instate)
@@ -1203,7 +1308,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3; struct POP3 *pop3 = data->req.protop;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
struct pingpong *pp = &pop3c->pp; struct pingpong *pp = &pop3c->pp;
@@ -1328,6 +1433,14 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
break; break;
#endif #endif
case POP3_AUTH_XOAUTH2:
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
break;
case POP3_AUTH_CANCEL:
result = pop3_state_auth_cancel_resp(conn, pop3code, pop3c->state);
break;
case POP3_AUTH_FINAL: case POP3_AUTH_FINAL:
result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state); result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
break; break;
@@ -1368,11 +1481,13 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone); result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &pop3c->ssldone);
else if(result || !pop3c->ssldone)
result = Curl_pp_statemach(&pop3c->pp, FALSE); return result;
}
result = Curl_pp_statemach(&pop3c->pp, FALSE);
*done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE;
return result; return result;
@@ -1395,13 +1510,11 @@ static CURLcode pop3_init(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3; struct POP3 *pop3;
if(!pop3) { pop3 = data->req.protop = calloc(sizeof(struct POP3), 1);
pop3 = data->state.proto.pop3 = calloc(sizeof(struct POP3), 1); if(!pop3)
if(!pop3) result = CURLE_OUT_OF_MEMORY;
result = CURLE_OUT_OF_MEMORY;
}
return result; return result;
} }
@@ -1431,15 +1544,6 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
*done = FALSE; /* default to not done yet */ *done = FALSE; /* default to not done yet */
/* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */
Curl_reset_reqproto(conn);
/* Initialise the POP3 layer */
result = pop3_init(conn);
if(result)
return result;
/* We always support persistent connections in POP3 */ /* We always support persistent connections in POP3 */
conn->bits.close = FALSE; conn->bits.close = FALSE;
@@ -1483,7 +1587,7 @@ static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3; struct POP3 *pop3 = data->req.protop;
(void)premature; (void)premature;
@@ -1521,12 +1625,12 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
{ {
/* This is POP3 and no proxy */ /* This is POP3 and no proxy */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct POP3 *pop3 = conn->data->req.protop;
DEBUGF(infof(conn->data, "DO phase starts\n")); DEBUGF(infof(conn->data, "DO phase starts\n"));
if(conn->data->set.opt_no_body) { if(conn->data->set.opt_no_body) {
/* Requested no body means no transfer */ /* Requested no body means no transfer */
struct POP3 *pop3 = conn->data->state.proto.pop3;
pop3->transfer = FTPTRANSFER_INFO; pop3->transfer = FTPTRANSFER_INFO;
} }
@@ -1563,15 +1667,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
/* Since connections can be re-used between SessionHandles, there might be a
connection already existing but on a fresh SessionHandle struct. As such
we make sure we have a good POP3 struct to play with. For new connections
the POP3 struct is allocated and setup in the pop3_connect() function. */
Curl_reset_reqproto(conn);
result = pop3_init(conn);
if(result)
return result;
/* Parse the URL path */ /* Parse the URL path */
result = pop3_parse_url_path(conn); result = pop3_parse_url_path(conn);
if(result) if(result)
@@ -1594,8 +1689,7 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
* Disconnect from an POP3 server. Cleanup protocol-specific per-connection * Disconnect from an POP3 server. Cleanup protocol-specific per-connection
* resources. BLOCKING. * resources. BLOCKING.
*/ */
static CURLcode pop3_disconnect(struct connectdata *conn, static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
bool dead_connection)
{ {
struct pop3_conn *pop3c = &conn->proto.pop3c; struct pop3_conn *pop3c = &conn->proto.pop3c;
@@ -1605,7 +1699,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn,
/* The POP3 session may or may not have been allocated/setup at this /* The POP3 session may or may not have been allocated/setup at this
point! */ point! */
if(!dead_connection && pop3c->pp.conn) if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
if(!pop3_perform_quit(conn)) if(!pop3_perform_quit(conn))
(void)pop3_block_statemach(conn); /* ignore errors on QUIT */ (void)pop3_block_statemach(conn); /* ignore errors on QUIT */
@@ -1685,6 +1779,11 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
{ {
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
/* Initialise the POP3 layer */
CURLcode result = pop3_init(conn);
if(result)
return result;
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel POP3 operations through the proxy, we /* Unless we have asked to tunnel POP3 operations through the proxy, we
switch and use HTTP operations only */ switch and use HTTP operations only */
@@ -1700,10 +1799,8 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
#endif #endif
} }
/* We explicitly mark this connection as persistent here as we're doing /* set it up as an HTTP connection instead */
POP3 over HTTP and thus we accidentally avoid setting this value return conn->handler->setup_connection(conn);
otherwise */
conn->bits.close = FALSE;
#else #else
failf(data, "POP3 over http proxy requires HTTP support built-in!"); failf(data, "POP3 over http proxy requires HTTP support built-in!");
return CURLE_UNSUPPORTED_PROTOCOL; return CURLE_UNSUPPORTED_PROTOCOL;
@@ -1745,30 +1842,34 @@ static CURLcode pop3_parse_url_options(struct connectdata *conn)
pop3c->preftype = POP3_TYPE_APOP; pop3c->preftype = POP3_TYPE_APOP;
pop3c->prefmech = SASL_AUTH_NONE; pop3c->prefmech = SASL_AUTH_NONE;
} }
else if(strequal(value, "LOGIN")) { else if(strequal(value, SASL_MECH_STRING_LOGIN)) {
pop3c->preftype = POP3_TYPE_SASL; pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_LOGIN; pop3c->prefmech = SASL_MECH_LOGIN;
} }
else if(strequal(value, "PLAIN")) { else if(strequal(value, SASL_MECH_STRING_PLAIN)) {
pop3c->preftype = POP3_TYPE_SASL; pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_PLAIN; pop3c->prefmech = SASL_MECH_PLAIN;
} }
else if(strequal(value, "CRAM-MD5")) { else if(strequal(value, SASL_MECH_STRING_CRAM_MD5)) {
pop3c->preftype = POP3_TYPE_SASL; pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_CRAM_MD5; pop3c->prefmech = SASL_MECH_CRAM_MD5;
} }
else if(strequal(value, "DIGEST-MD5")) { else if(strequal(value, SASL_MECH_STRING_DIGEST_MD5)) {
pop3c->preftype = POP3_TYPE_SASL; pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_DIGEST_MD5; pop3c->prefmech = SASL_MECH_DIGEST_MD5;
} }
else if(strequal(value, "GSSAPI")) { else if(strequal(value, SASL_MECH_STRING_GSSAPI)) {
pop3c->preftype = POP3_TYPE_SASL; pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_GSSAPI; pop3c->prefmech = SASL_MECH_GSSAPI;
} }
else if(strequal(value, "NTLM")) { else if(strequal(value, SASL_MECH_STRING_NTLM)) {
pop3c->preftype = POP3_TYPE_SASL; pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_NTLM; pop3c->prefmech = SASL_MECH_NTLM;
} }
else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
pop3c->preftype = POP3_TYPE_SASL;
pop3c->prefmech = SASL_MECH_XOAUTH2;
}
else { else {
pop3c->preftype = POP3_TYPE_NONE; pop3c->preftype = POP3_TYPE_NONE;
pop3c->prefmech = SASL_AUTH_NONE; pop3c->prefmech = SASL_AUTH_NONE;
@@ -1791,7 +1892,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
{ {
/* The POP3 struct is already initialised in pop3_connect() */ /* The POP3 struct is already initialised in pop3_connect() */
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3; struct POP3 *pop3 = data->req.protop;
const char *path = data->state.path; const char *path = data->state.path;
/* URL decode the path for the message ID */ /* URL decode the path for the message ID */
@@ -1808,7 +1909,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct POP3 *pop3 = data->state.proto.pop3; struct POP3 *pop3 = data->req.protop;
const char *custom = data->set.str[STRING_CUSTOMREQUEST]; const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */ /* URL decode the custom request */

View File

@@ -43,6 +43,8 @@ typedef enum {
POP3_AUTH_DIGESTMD5_RESP, POP3_AUTH_DIGESTMD5_RESP,
POP3_AUTH_NTLM, POP3_AUTH_NTLM,
POP3_AUTH_NTLM_TYPE2MSG, POP3_AUTH_NTLM_TYPE2MSG,
POP3_AUTH_XOAUTH2,
POP3_AUTH_CANCEL,
POP3_AUTH_FINAL, POP3_AUTH_FINAL,
POP3_APOP, POP3_APOP,
POP3_USER, POP3_USER,
@@ -91,7 +93,7 @@ extern const struct Curl_handler Curl_handler_pop3s;
/* Authentication type values */ /* Authentication type values */
#define POP3_TYPE_NONE 0 #define POP3_TYPE_NONE 0
#define POP3_TYPE_ANY ~0 #define POP3_TYPE_ANY ~0U
/* This is the 5-bytes End-Of-Body marker for POP3 */ /* This is the 5-bytes End-Of-Body marker for POP3 */
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" #define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"

View File

@@ -204,6 +204,12 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
case CURL_SSLVERSION_SSLv3: case CURL_SSLVERSION_SSLv3:
h->protocol = SSL_VERSION_3; h->protocol = SSL_VERSION_3;
break; break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
failf(data, "TLS minor version cannot be set");
return CURLE_SSL_CONNECT_ERROR;
} }
h->peerCert = NULL; h->peerCert = NULL;

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

View File

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

View File

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

View File

@@ -33,7 +33,7 @@
typedef unsigned long u_int32_t; typedef unsigned long u_int32_t;
/* System API wrapper prototypes and definitions to support ASCII parameters. */ /* System API wrapper prototypes & definitions to support ASCII parameters. */
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
@@ -42,7 +42,8 @@ typedef unsigned long u_int32_t;
#include <qsoasync.h> #include <qsoasync.h>
#include <gssapi.h> #include <gssapi.h>
extern int Curl_getaddrinfo_a(const char * nodename, const char * servname, extern int Curl_getaddrinfo_a(const char * nodename,
const char * servname,
const struct addrinfo * hints, const struct addrinfo * hints,
struct addrinfo * * res); struct addrinfo * * res);
#define getaddrinfo Curl_getaddrinfo_a #define getaddrinfo Curl_getaddrinfo_a
@@ -66,7 +67,8 @@ extern int Curl_SSL_Init_a(SSLInit * init);
#define SSL_Init Curl_SSL_Init_a #define SSL_Init Curl_SSL_Init_a
extern char * Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp); extern char * Curl_SSL_Strerror_a(int sslreturnvalue,
SSLErrorMsg * serrmsgp);
#define SSL_Strerror Curl_SSL_Strerror_a #define SSL_Strerror Curl_SSL_Strerror_a
@@ -226,5 +228,12 @@ extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
#define sendto Curl_os400_sendto #define sendto Curl_os400_sendto
#define recvfrom Curl_os400_recvfrom #define recvfrom Curl_os400_recvfrom
#ifdef HAVE_LIBZ
#define zlibVersion Curl_os400_zlibVersion
#define inflateInit_ Curl_os400_inflateInit_
#define inflateInit2_ Curl_os400_inflateInit2_
#define inflate Curl_os400_inflate
#define inflateEnd Curl_os400_inflateEnd
#endif
#endif /* HEADER_CURL_SETUP_OS400_H */ #endif /* HEADER_CURL_SETUP_OS400_H */

78
lib/sigpipe.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef HEADER_CURL_SIGPIPE_H
#define HEADER_CURL_SIGPIPE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL)
#include <signal.h>
struct sigpipe_ignore {
struct sigaction old_pipe_act;
bool no_signal;
};
#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x
/*
* sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl
* internals, and then sigpipe_restore() will restore the situation when we
* return from libcurl again.
*/
static void sigpipe_ignore(struct SessionHandle *data,
struct sigpipe_ignore *ig)
{
/* get a local copy of no_signal because the SessionHandle might not be
around when we restore */
ig->no_signal = data->set.no_signal;
if(!data->set.no_signal) {
struct sigaction action;
/* first, extract the existing situation */
memset(&ig->old_pipe_act, 0, sizeof(struct sigaction));
sigaction(SIGPIPE, NULL, &ig->old_pipe_act);
action = ig->old_pipe_act;
/* ignore this signal */
action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &action, NULL);
}
}
/*
* sigpipe_restore() puts back the outside world's opinion of signal handler
* and SIGPIPE handling. It MUST only be called after a corresponding
* sigpipe_ignore() was used.
*/
static void sigpipe_restore(struct sigpipe_ignore *ig)
{
if(!ig->no_signal)
/* restore the outside state */
sigaction(SIGPIPE, &ig->old_pipe_act, NULL);
}
#else
/* for systems without sigaction */
#define sigpipe_ignore(x,y) Curl_nop_stmt
#define sigpipe_restore(x) Curl_nop_stmt
#define SIGPIPE_VARIABLE(x)
#endif
#endif /* HEADER_CURL_SIGPIPE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -44,7 +44,10 @@ typedef enum {
SMTP_AUTH_DIGESTMD5_RESP, SMTP_AUTH_DIGESTMD5_RESP,
SMTP_AUTH_NTLM, SMTP_AUTH_NTLM,
SMTP_AUTH_NTLM_TYPE2MSG, SMTP_AUTH_NTLM_TYPE2MSG,
SMTP_AUTH_XOAUTH2,
SMTP_AUTH_CANCEL,
SMTP_AUTH_FINAL, SMTP_AUTH_FINAL,
SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */
SMTP_MAIL, /* MAIL FROM */ SMTP_MAIL, /* MAIL FROM */
SMTP_RCPT, /* RCPT TO */ SMTP_RCPT, /* RCPT TO */
SMTP_DATA, SMTP_DATA,
@@ -59,6 +62,7 @@ typedef enum {
used. */ used. */
struct SMTP { struct SMTP {
curl_pp_transfer transfer; curl_pp_transfer transfer;
char *custom; /* Custom Request */
struct curl_slist *rcpt; /* Recipient list */ struct curl_slist *rcpt; /* Recipient list */
size_t eob; /* Number of bytes of the EOB (End Of Body) that size_t eob; /* Number of bytes of the EOB (End Of Body) that
have been received so far */ have been received so far */

View File

@@ -129,6 +129,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
curlx_nonblock(sock, FALSE); curlx_nonblock(sock, FALSE);
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
/* /*
* Compose socks4 request * Compose socks4 request
* *
@@ -182,6 +184,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
else else
hp = NULL; /* fail! */ hp = NULL; /* fail! */
infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
Curl_resolv_unlock(data, dns); /* not used anymore from now on */ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
} }

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