Compare commits

...

246 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
175 changed files with 6496 additions and 2171 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,68 +1,71 @@
Curl and libcurl 7.33.0 Curl and libcurl 7.34.0
Public curl releases: 135 Public curl releases: 136
Command line options: 161 Command line options: 161
curl_easy_setopt() options: 205 curl_easy_setopt() options: 206
Public functions in libcurl: 58 Public functions in libcurl: 58
Known libcurl bindings: 42 Known libcurl bindings: 42
Contributors: 1057 Contributors: 1104
This release includes the following security fix:
o gtls: respect *VERIFYHOST independently of *VERIFYPEER [26]
This release includes the following changes: This release includes the following changes:
o test code for testing the event based API [3] o SSL: protocol version can be specified more precisely [1]
o CURLM_ADDED_ALREADY: new error code o imap/pop3/smtp: Added graceful cancellation of SASL authentication
o test TFTP server: support "writedelay" within <servercmd> o Add "Happy Eyeballs" for IPv4/IPv6 dual connect attempts
o krb4 support has been removed o base64: Added validation of base64 input strings when decoding [8]
o imap/pop3/smtp: added basic SASL XOAUTH2 support [9] o curl_easy_setopt: Added the ability to set the login options separately
o darwinssl: add support for PKCS#12 files for client authentication o smtp: Added support for additional SMTP commands
o darwinssl: enable BEAST workaround on iOS 7 & later o curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals
o Pass password to OpenSSL engine by user interface [15] o nss: allow to use TLS > 1.0 if built against recent NSS [18]
o c-ares: Add support for various DNS binding options o SECURITY: added this document to describe our security processes [22]
o cookies: add expiration o parseconfig: warn if unquoted white spaces are detected
o curl: added --oauth2-bearer option
This release includes the following bugfixes: This release includes the following bugfixes:
o nss: make sure that NSS is initialized o darwinssl: un-break iOS build after PKCS#12 feature added
o curl: make --no-[option] work properly for several options o tool: use XFERFUNCTION to save some casts [2]
o FTP: with socket_action send better socket updates in active mode [1] o usercertinmem: fix memory leaks
o curl: fix the --sasl-ir in the --help output o ssh: Handle successful SSH_USERAUTH_NONE [3]
o tests 2032, 2033: Don't hardcode port in expected output o NSS: acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option [4]
o urlglob: better detect unclosed braces, empty lists and overflows [7] o test906: Fixed failing test on some platforms [5]
o urlglob: error out on range overflow [8] o sasl: initialize NSS before using NTLM crypto
o imap: Fixed response check for SEARCH, EXPUNGE, LSUB, UID and NOOP commands [10] o sasl: Fixed memory leak in OAUTH2 message creation
o handle arbitrary-length username and password [2] o imap/pop3/smtp: Fixed QUIT / LOGOUT being sent when SSL connect fails
o TFTP: make the CURLOPT_LOW_SPEED* options work [4] o cmake: unbreak for non-Windows platforms [6]
o curl.h: name space pollution by "enum type" [5] o ssh: initialize per-handle data in ssh_connect()
o multi: move on from STATE_DONE faster [6] o glob: fix broken URLs
o FTP: 60 secs delay if aborted in the CURLOPT_HEADERFUNCTION callback [11] o configure: check for long long when building with cyassl
o multi_socket: improved 100-continue timeout handling o CURLOPT_RESOLVE: mention they don't time-out [7]
o curl_multi_remove_handle: allow multiple removes o docs/examples/httpput.c: fix build for MSVC
o FTP: fix getsock during DO_MORE state [12] o FTP: make the data connection work when going through proxy
o -x: rephrased the --proxy section somewhat o NSS: support for CERTINFO feature
o acinclude: fix --without-ca-path when cross-compiling [13] o curl_multi_wait: accept 0 from multi_timeout() as valid timeout
o LDAP: fix bad free() when URL parsing failed [14] o glob_range: pass the closing bracket for a-z ranges
o --data: mention CRLF treatment when reading from file o tool_help: Updated --list-only description to include POP3
o curl_easy_pause: suggest one way to unpause o Curl_ssl_push_certinfo_len: don't %.*s non-zero-terminated string [9]
o imap: Fixed calculation of transfer when partial FETCH received [16] o cmake: fix Windows build with IPv6 support [10]
o pingpong: Check SSL library buffers for already read data [16] o ares: Fixed compilation under Visual Studio 2012 [11]
o imap/pop3/smtp: Speed up SSL connection initialization o curl_easy_setopt.3: clarify CURLOPT_SSL_VERIFYHOST documentation [12]
o libcurl.3: for multi interface connections are held in the multi handle o curl.1: mention that -O does no URL decoding [13]
o curl_easy_setopt.3: mention RTMP URL quirks [17] o darwinssl: PKCS#12 import feature now requires Lion or later [14]
o curl.1: detail how short/long options work [18] o darwinssl: check for SSLSetSessionOption() presence when toggling BEAST
o curl.1: Added information about optional login options to --user option o configure: Fix test with -Werror=implicit-function-declaration [15]
o curl: Added clarification to the --mail options in the --help output o sigpipe: factor out sigpipe_reset from easy.c
o curl_easy_setopt.3: clarify that TIMEOUT and TIMEOUT_MS set the same value o curl_multi_cleanup: ignore SIGPIPE
o openssl: use correct port number in error message [19] o globbing: curl glob counter mismatch with {} list use [16]
o darwinssl: block TLS_RSA_WITH_NULL_SHA256 cipher o parseconfig: dash options can't specified with colon or equals [17]
o OpenSSL: acknowledge CURLOPT_SSL_VERIFYHOST without VERIFYPEER o digest: fix CURLAUTH_DIGEST_IE [19]
o xattr: add support for FreeBSD xattr API o curl.h: <sys/select.h> for OpenBSD [20]
o win32: fix Visual Studio 2010 build with WINVER >= 0x600 [22] o darwinssl: Fix #if 10.6.0 for SecKeychainSearch
o configure: use icc options without space [21] o TFTP: fix return codes for connect timeout [21]
o test1112: Increase the timeout from 7s to 16s [20] o login options: remove the ;[options] support from CURLOPT_USERPWD [23]
o SCP: upload speed on a fast connection limited to 16384 B/s o imap: Fixed incorrect fallback to clear text authentication
o curl_setup_once: fix errno access for lwip on Windows [24] o parsedate: avoid integer overflow
o HTTP: Output http response 304 when modified time is too old [23] o curl.1: document -J doesn't %-decode [25]
o multi: add timer inaccuracy margin to timeout/connecttimeout [24]
This release includes the following known bugs: This release includes the following known bugs:
@@ -71,41 +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 McLellan, Bill Doyle, Colby Ranger, Fabian Keil, Gisle Vanem, Alessandro Ghedini, Andreas Rieke, Björn Stenberg, Chris Conlon,
John E. Malmberg, Jonathan Nieder, Kamil Dudka, Shawn Landden, Christian Grothoff, Christian Weisgerber, Dave Reisner, David Walser,
Tor Arntsen, Will Dietz, Yi Huang, Kyle L. Huff, Steve Holme, Mike Mio, Dima Tisnek, Fabian Keil, Felix Yan, Gergely Nagy, Gisle Vanem,
Stefan Neis, Nick Zitzmann, Geoff Beier, John Dunn, Jiri Hruska, Ishan SinghLevett, James Dury, Javier Barroso, Jeff King, Kamil Dudka,
Tomas Mlcoch, Kim Vandry, Ben Greear, Gorilla Maguila, Jerry Krinock, Kim Vandry, Marcin Gryszkalis, Melissa Mears, Michael Osipov, Nick Zitzmann,
Yamada Yasuharu, Gordon Marler, Dave Thompson, D. Flinkmann, Oliver Kuckertz, Patrick Monnerat, Paul Donohue, Paul Marks, Romulo A. Ceccon,
Benoit Sigoure, Clemens Gruber, Guenter Knauf, Petr Pisar, Elmira A Semenova, Rémy Léone, Sergey Tatarincev, Steve Holme, Tomas Hoger, Tyler Hall,
Francois Charlier, Ishan SinghLevett, Marcel Raad, Ulf Samuelsson, Yaakov Selkowitz, Eric Lubin, Petr Bahula, He Qin, Marc Deslauriers
Andrej E Baranov, Derek Higgins, Heinrich Schaefer
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/mail/lib-2013-08/0043.html [1] = https://github.com/bagder/curl/pull/79
[2] = http://bugs.debian.org/719856 [2] = http://curl.haxx.se/mail/lib-2013-10/0089.html
[3] = http://daniel.haxx.se/blog/2013/08/20/testing-curl_multi_socket_action/ [3] = http://curl.haxx.se/mail/lib-2013-10/0096.html
[4] = http://curl.haxx.se/bug/view.cgi?id=1269 [4] = http://curl.haxx.se/mail/lib-2013-10/0113.html
[5] = https://github.com/bagder/curl/pull/76 [5] = http://sourceforge.net/p/curl/bugs/1291
[6] = http://curl.haxx.se/mail/lib-2013-08/0211.html [6] = http://sourceforge.net/p/curl/bugs/1292
[7] = http://curl.haxx.se/bug/view.cgi?id=1264 [7] = http://curl.haxx.se/mail/lib-2013-10/0062.html
[8] = http://curl.haxx.se/bug/view.cgi?id=1267 [8] = http://curl.haxx.se/mail/lib-2013-10/0242.html
[9] = http://curl.haxx.se/mail/lib-2013-08/0234.html [9] = http://curl.haxx.se/bug/view.cgi?id=1295
[10] = http://curl.haxx.se/mail/lib-2013-08/0136.html [10] = http://sourceforge.net/p/curl/bugs/1064
[11] = https://bugzilla.redhat.com/1005686 [11] = http://curl.haxx.se/mail/lib-2013-11/0057.html
[12] = http://curl.haxx.se/mail/lib-2013-08/0109.html [12] = https://github.com/bagder/curl/pull/83
[13] = http://curl.haxx.se/bug/view.cgi?id=1273 [13] = http://sourceforge.net/p/curl/bugs/1299
[14] = http://curl.haxx.se/mail/lib-2013-08/0209.html [14] = http://curl.haxx.se/mail/lib-2013-11/0076.html
[15] = http://curl.haxx.se/mail/lib-2013-08/0265.html [15] = http://curl.haxx.se/bug/view.cgi?id=1304
[16] = http://curl.haxx.se/mail/lib-2013-08/0170.html [16] = http://curl.haxx.se/bug/view.cgi?id=1305
[17] = http://curl.haxx.se/bug/view.cgi?id=1278 [17] = http://curl.haxx.se/bug/view.cgi?id=1297
[18] = http://curl.haxx.se/bug/view.cgi?id=1279 [18] = http://curl.haxx.se/mail/lib-2013-11/0162.html
[19] = http://curl.haxx.se/bug/view.cgi?id=1281 [19] = http://curl.haxx.se/bug/view.cgi?id=1308
[20] = http://curl.haxx.se/mail/lib-2010-02/0200.html [20] = http://curl.haxx.se/mail/lib-2013-12/0017.html
[21] = http://curl.haxx.se/mail/lib-2013-09/0182.html [21] = http://curl.haxx.se/bug/view.cgi?id=1310
[22] = http://curl.haxx.se/bug/view.cgi?id=1282 [22] = http://curl.haxx.se/dev/security.html
[23] = http://curl.haxx.se/bug/view.cgi?id=1288 [23] = http://curl.haxx.se/bug/view.cgi?id=1311
[24] = http://curl.haxx.se/mail/lib-2013-10/0048.html [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

@@ -1065,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)
@@ -1983,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
@@ -2067,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])
@@ -2084,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

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,25 @@ 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 84. CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
backends, so relying on this information in a generic app is flaky. backends, so relying on this information in a generic app is flaky.

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

@@ -646,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.
@@ -711,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
@@ -722,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.
@@ -742,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:
@@ -806,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),
@@ -894,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
@@ -1053,11 +1074,15 @@ 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" .IP "--oauth2-bearer"
(IMAP/POP3/SMTP) Specify the Bearer Token for OAUTH 2.0 server authentication. (IMAP, POP3, SMTP)
The Bearer Token is used in conjuction with the user name which can be Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
specified as part of the \fI--url\fP or \fI-u, --user\fP options. 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. The Bearer Token and user name are formatted according to RFC 6750.
@@ -1498,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.
@@ -1761,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
@@ -2055,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

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

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

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

@@ -1131,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
@@ -1145,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
@@ -1164,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.
@@ -1651,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
@@ -2028,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
@@ -2066,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
@@ -2293,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
@@ -2364,7 +2412,7 @@ prefix, in order to avoid confusion with a nickname.
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", except the format of your certificate. Supported formats are "PEM" and "DER", except
with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
(on iOS 5 or later, or OS X 10.6 or later) also support "P12" for (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) 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
@@ -2410,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
@@ -2417,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.
@@ -2522,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.
@@ -2534,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

@@ -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
@@ -394,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
@@ -593,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
@@ -695,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

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
@@ -827,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. */
@@ -1388,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. */
@@ -1569,6 +1568,9 @@ typedef enum {
* Only supported by the c-ares DNS backend */ * Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223), 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;
@@ -1659,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 */
}; };
@@ -1980,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
@@ -2031,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

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.33.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 33 #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 0x072100 #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
@@ -269,6 +269,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
(option) == CURLOPT_DNS_INTERFACE || \ (option) == CURLOPT_DNS_INTERFACE || \
(option) == CURLOPT_DNS_LOCAL_IP4 || \ (option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \ (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

@@ -46,4 +46,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.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 http2.h sigpipe.h

View File

@@ -645,10 +645,10 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
const char *local_ip4) const char *local_ip4)
{ {
#if (ARES_VERSION >= 0x010704) #if (ARES_VERSION >= 0x010704)
uint32_t a4; struct in_addr a4;
if((!local_ip4) || (local_ip4[0] == 0)) { if((!local_ip4) || (local_ip4[0] == 0)) {
a4 = 0; /* disabled: do not bind to a specific address */ a4.s_addr = 0; /* disabled: do not bind to a specific address */
} }
else { else {
if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) { if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
@@ -656,7 +656,7 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
} }
} }
ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4)); ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr));
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */

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

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

@@ -834,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,
@@ -874,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)
@@ -914,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);
@@ -938,8 +938,10 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
cPassword, kCFStringEncodingUTF8) : NULL; cPassword, kCFStringEncodingUTF8) : NULL;
CFDataRef pkcs_data = NULL; CFDataRef pkcs_data = NULL;
/* We can import P12 files on iOS or OS X 10.6 or later: */ /* We can import P12 files on iOS or OS X 10.7 or later: */
#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS /* 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, if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
NULL, NULL, &status)) { NULL, NULL, &status)) {
const void *cKeys[] = {kSecImportExportPassphrase}; const void *cKeys[] = {kSecImportExportPassphrase};
@@ -963,7 +965,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
CFRelease(options); CFRelease(options);
CFRelease(pkcs_data); CFRelease(pkcs_data);
} }
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
if(password) if(password)
CFRelease(password); CFRelease(password);
CFRelease(pkcs_url); CFRelease(pkcs_url);
@@ -1056,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);
@@ -1100,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,
@@ -1130,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,
@@ -1216,16 +1252,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
} }
else { else {
switch(err) { switch(err) {
case errSecPkcs12VerifyFailure: case errSecAuthFailed: case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
failf(data, "SSL: Incorrect password for the certificate \"%s\" " failf(data, "SSL: Incorrect password for the certificate \"%s\" "
"and its private key.", data->set.str[STRING_CERT]); "and its private key.", data->set.str[STRING_CERT]);
break; break;
case errSecDecode: case errSecUnknownFormat: case errSecDecode: case -25257: /* errSecUnknownFormat */
failf(data, "SSL: Couldn't make sense of the data in the " failf(data, "SSL: Couldn't make sense of the data in the "
"certificate \"%s\" and its private key.", "certificate \"%s\" and its private key.",
data->set.str[STRING_CERT]); data->set.str[STRING_CERT]);
break; break;
case errSecPassphraseRequired: case -25260: /* errSecPassphraseRequired */
failf(data, "SSL The certificate \"%s\" requires a password.", failf(data, "SSL The certificate \"%s\" requires a password.",
data->set.str[STRING_CERT]); data->set.str[STRING_CERT]);
break; break;
@@ -1403,7 +1439,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 #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 /* We want to enable 1/n-1 when using a CBC cipher unless the user
specifically doesn't want us doing that: */ specifically doesn't want us doing that: */
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord, if(SSLSetSessionOption != NULL)
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
!data->set.ssl_enable_beast); !data->set.ssl_enable_beast);
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */

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

@@ -23,6 +23,7 @@
* 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 * RFC6749 OAuth 2.0 Authorization Framework
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -40,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>
@@ -50,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,
@@ -59,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;
@@ -163,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
@@ -172,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
@@ -182,47 +217,36 @@ 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; 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 */
response = aprintf( 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],
@@ -231,13 +255,74 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
if(!response) if(!response)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */ /* Base64 encode the response */
result = Curl_base64_encode(data, response, 0, outptr, outlen); result = Curl_base64_encode(data, response, 0, outptr, outlen);
Curl_safefree(response); Curl_safefree(response);
return result; 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;
}
/* /*
* Curl_sasl_create_digest_md5_message() * Curl_sasl_create_digest_md5_message()
* *
@@ -247,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.
@@ -258,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);
@@ -401,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
@@ -438,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);
} }
/* /*
@@ -451,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.
@@ -462,33 +546,27 @@ 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);
if(!result)
result = Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm,
outptr, outlen);
return result;
} }
#endif /* USE_NTLM */ #endif /* USE_NTLM */
/* /*
* Curl_sasl_create_xoauth2_message() * Curl_sasl_create_xoauth2_message()
* *
* This is used to generate an already encoded XOAUTH2 message ready * This is used to generate an already encoded OAuth 2.0 message ready for
* for sending to the recipient. * sending to the recipient.
* *
* Parameters: * Parameters:
* *
* data [in] - The session handle. * data [in] - The session handle.
* user [in] - The user name. * user [in] - The user name.
* bearer [in] - The XOAUTH Bearer token. * bearer [in] - The bearer token.
* 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.
@@ -500,16 +578,20 @@ CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
const char *bearer, const char *bearer,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
char *xoauth; CURLcode result = CURLE_OK;
char *xoauth = NULL;
/* Generate the message */
xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer); xoauth = aprintf("user=%s\1auth=Bearer %s\1\1", user, bearer);
if(!xoauth) if(!xoauth)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* Base64 encode the reply */ /* Base64 encode the reply */
return Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
outlen);
Curl_safefree(xoauth);
return result;
} }
/* /*

View File

@@ -66,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,
@@ -90,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,

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

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

188
lib/ftp.c
View File

@@ -1802,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) &&
@@ -1851,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 ||
@@ -1860,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
@@ -1916,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 */
@@ -1957,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 */
@@ -1985,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->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 */
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 */
@@ -3625,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)) {

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

@@ -187,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++;
@@ -224,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)
@@ -699,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
@@ -709,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.
@@ -744,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;
@@ -760,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);
@@ -779,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
@@ -798,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;
} }
} }
@@ -820,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");
} }
@@ -833,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");
@@ -843,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) {
@@ -857,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;
} }
@@ -1831,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)
@@ -3247,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)
@@ -3259,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) {
@@ -3455,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;
} }
@@ -3463,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

@@ -35,11 +35,12 @@ extern const struct Curl_handler Curl_handler_http;
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);
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* /*
@@ -81,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);

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

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

@@ -27,6 +27,7 @@
* 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 * RFC6749 OAuth 2.0 Authorization Framework
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -370,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()
@@ -396,6 +426,7 @@ static void state(struct connectdata *conn, imapstate newstate)
"AUTHENTICATE_NTLM", "AUTHENTICATE_NTLM",
"AUTHENTICATE_NTLM_TYPE2MSG", "AUTHENTICATE_NTLM_TYPE2MSG",
"AUTHENTICATE_XOAUTH2", "AUTHENTICATE_XOAUTH2",
"AUTHENTICATE_CANCEL",
"AUTHENTICATE_FINAL", "AUTHENTICATE_FINAL",
"LOGIN", "LOGIN",
"LIST", "LIST",
@@ -553,8 +584,8 @@ 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)) {
@@ -622,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);
@@ -639,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 {
@@ -976,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;
} }
@@ -1013,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;
} }
@@ -1050,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;
} }
@@ -1075,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 */
@@ -1086,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;
} }
@@ -1128,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 */
@@ -1139,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;
} }
@@ -1211,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;
} }
@@ -1235,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 */
@@ -1245,31 +1276,40 @@ 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 AUTH XOAUTH2 (without initial response) responses */ /* For AUTHENTICATE XOAUTH2 (without initial response) responses */
static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn, static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
int imapcode, int imapcode,
imapstate instate) imapstate instate)
@@ -1290,24 +1330,36 @@ static CURLcode imap_state_auth_xoauth2_resp(struct connectdata *conn,
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer, conn->xoauth2_bearer,
&xoauth, &len); &xoauth, &len);
if(!result && xoauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
/* Send the message */ if(!result)
if(!result) { state(conn, IMAP_AUTHENTICATE_FINAL);
if(xoauth) {
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
if(!result)
state(conn, IMAP_AUTHENTICATE_FINAL);
}
Curl_safefree(xoauth);
} }
} }
Curl_safefree(xoauth);
return result; return result;
} }
/* For final responses to the AUTHENTICATE sequence */ /* 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)
@@ -1660,6 +1712,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state); result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
break; 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;
@@ -1782,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 */
@@ -1982,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 */
@@ -2276,24 +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, SASL_MECH_STRING_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, SASL_MECH_STRING_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, SASL_MECH_STRING_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, SASL_MECH_STRING_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, SASL_MECH_STRING_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, SASL_MECH_STRING_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 if(strequal(value, SASL_MECH_STRING_XOAUTH2)) }
else if(strequal(value, SASL_MECH_STRING_XOAUTH2)) {
imapc->preftype = IMAP_TYPE_SASL;
imapc->prefmech = SASL_MECH_XOAUTH2; imapc->prefmech = SASL_MECH_XOAUTH2;
else }
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;

View File

@@ -44,6 +44,7 @@ typedef enum {
IMAP_AUTHENTICATE_NTLM, IMAP_AUTHENTICATE_NTLM,
IMAP_AUTHENTICATE_NTLM_TYPE2MSG, IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
IMAP_AUTHENTICATE_XOAUTH2, IMAP_AUTHENTICATE_XOAUTH2,
IMAP_AUTHENTICATE_CANCEL,
IMAP_AUTHENTICATE_FINAL, IMAP_AUTHENTICATE_FINAL,
IMAP_LOGIN, IMAP_LOGIN,
IMAP_LIST, IMAP_LIST,
@@ -77,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 */
@@ -91,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

@@ -41,6 +41,7 @@
#include "bundles.h" #include "bundles.h"
#include "multihandle.h" #include "multihandle.h"
#include "pipeline.h" #include "pipeline.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>
@@ -621,17 +622,28 @@ static int waitconnect_getsock(struct connectdata *conn,
curl_socket_t *sock, curl_socket_t *sock,
int numsocks) int numsocks)
{ {
int i;
int s=0;
int rc=0;
if(!numsocks) if(!numsocks)
return GETSOCK_BLANK; return GETSOCK_BLANK;
sock[0] = conn->sock[FIRSTSOCKET]; for(i=0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
sock[s] = conn->tempsock[i];
rc |= GETSOCK_WRITESOCK(s++);
}
}
/* when we've sent a CONNECT to a proxy, we should rather wait for the /* when we've sent a CONNECT to a proxy, we should rather wait for the
socket to become readable to be able to get the response headers */ socket to become readable to be able to get the response headers */
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) {
return GETSOCK_READSOCK(0); sock[0] = conn->sock[FIRSTSOCKET];
rc = GETSOCK_READSOCK(0);
}
return GETSOCK_WRITESOCK(0); return rc;
} }
static int domore_getsock(struct connectdata *conn, static int domore_getsock(struct connectdata *conn,
@@ -778,9 +790,9 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
/* If the internally desired timeout is actually shorter than requested from /* If the internally desired timeout is actually shorter than requested from
the outside, then use the shorter time! But only if the internal timer the outside, then use the shorter time! But only if the internal timer
is actually larger than 0! */ is actually larger than -1! */
(void)multi_timeout(multi, &timeout_internal); (void)multi_timeout(multi, &timeout_internal);
if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms)) if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
timeout_ms = (int)timeout_internal; timeout_ms = (int)timeout_internal;
/* Count up how many fds we have from the multi handle */ /* Count up how many fds we have from the multi handle */
@@ -865,6 +877,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
if(nfds) { if(nfds) {
/* wait... */ /* wait... */
infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
i = Curl_poll(ufds, nfds, timeout_ms); i = Curl_poll(ufds, nfds, timeout_ms);
if(i) { if(i) {
@@ -1774,12 +1787,18 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
struct SessionHandle *nextdata; struct SessionHandle *nextdata;
if(GOOD_MULTI_HANDLE(multi)) { if(GOOD_MULTI_HANDLE(multi)) {
bool restore_pipe = FALSE;
SIGPIPE_VARIABLE(pipe_st);
multi->type = 0; /* not good anymore */ multi->type = 0; /* not good anymore */
/* Close all the connections in the connection cache */ /* Close all the connections in the connection cache */
close_all_connections(multi); close_all_connections(multi);
if(multi->closure_handle) { if(multi->closure_handle) {
sigpipe_ignore(multi->closure_handle, &pipe_st);
restore_pipe = TRUE;
multi->closure_handle->dns.hostcache = multi->hostcache; multi->closure_handle->dns.hostcache = multi->hostcache;
Curl_hostcache_clean(multi->closure_handle, Curl_hostcache_clean(multi->closure_handle,
multi->closure_handle->dns.hostcache); multi->closure_handle->dns.hostcache);
@@ -1824,6 +1843,8 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl);
free(multi); free(multi);
if(restore_pipe)
sigpipe_restore(&pipe_st);
return CURLM_OK; return CURLM_OK;
} }

View File

@@ -30,6 +30,8 @@
#define MULTI_TIMEOUT_INACCURACY 3000 #define MULTI_TIMEOUT_INACCURACY 3000
#endif #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
*/ */

187
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");

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

@@ -29,6 +29,7 @@
* RFC4616 PLAIN authentication * RFC4616 PLAIN authentication
* RFC5034 POP3 SASL Authentication Mechanism * RFC5034 POP3 SASL Authentication Mechanism
* RFC6749 OAuth 2.0 Authorization Framework * RFC6749 OAuth 2.0 Authorization Framework
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -349,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()
@@ -375,6 +405,7 @@ static void state(struct connectdata *conn, pop3state newstate)
"AUTH_NTLM", "AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG", "AUTH_NTLM_TYPE2MSG",
"AUTH_XOAUTH2", "AUTH_XOAUTH2",
"AUTH_CANCEL",
"AUTH_FINAL", "AUTH_FINAL",
"APOP", "APOP",
"USER", "USER",
@@ -570,8 +601,8 @@ 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) &&
@@ -834,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;
} }
@@ -871,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;
} }
@@ -908,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;
} }
@@ -933,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 */
@@ -944,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;
} }
@@ -986,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 */
@@ -997,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;
} }
@@ -1069,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;
} }
@@ -1093,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 */
@@ -1103,26 +1133,35 @@ 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
@@ -1147,24 +1186,36 @@ static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer, conn->xoauth2_bearer,
&xoauth, &len); &xoauth, &len);
if(!result && xoauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
/* Send the message */ if(!result)
if(!result) { state(conn, POP3_AUTH_FINAL);
if(xoauth) {
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
if(!result)
state(conn, POP3_AUTH_FINAL);
}
Curl_safefree(xoauth);
} }
} }
Curl_safefree(xoauth);
return result; return result;
} }
/* For final responses to the AUTH sequence */ /* 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)
@@ -1386,6 +1437,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state); result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
break; 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;
@@ -1570,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->req.protop;
pop3->transfer = FTPTRANSFER_INFO; pop3->transfer = FTPTRANSFER_INFO;
} }
@@ -1634,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;
@@ -1645,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 */

View File

@@ -44,6 +44,7 @@ typedef enum {
POP3_AUTH_NTLM, POP3_AUTH_NTLM,
POP3_AUTH_NTLM_TYPE2MSG, POP3_AUTH_NTLM_TYPE2MSG,
POP3_AUTH_XOAUTH2, POP3_AUTH_XOAUTH2,
POP3_AUTH_CANCEL,
POP3_AUTH_FINAL, POP3_AUTH_FINAL,
POP3_APOP, POP3_APOP,
POP3_USER, POP3_USER,
@@ -92,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

@@ -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 */

View File

@@ -27,7 +27,8 @@
* RFC4954 SMTP Authentication * RFC4954 SMTP Authentication
* RFC5321 SMTP protocol * RFC5321 SMTP protocol
* RFC6749 OAuth 2.0 Authorization Framework * RFC6749 OAuth 2.0 Authorization Framework
* Draft SMTP URL Interface * Draft SMTP URL Interface <draft-earhart-url-smtp-00.txt>
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
* *
***************************************************************************/ ***************************************************************************/
@@ -103,6 +104,7 @@ static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
static CURLcode smtp_setup_connection(struct connectdata *conn); static CURLcode smtp_setup_connection(struct connectdata *conn);
static CURLcode smtp_parse_url_options(struct connectdata *conn); static CURLcode smtp_parse_url_options(struct connectdata *conn);
static CURLcode smtp_parse_url_path(struct connectdata *conn); static CURLcode smtp_parse_url_path(struct connectdata *conn);
static CURLcode smtp_parse_custom_request(struct connectdata *conn);
/* /*
* SMTP protocol handler. * SMTP protocol handler.
@@ -218,7 +220,7 @@ static void smtp_to_smtps(struct connectdata *conn)
/*********************************************************************** /***********************************************************************
* *
* pop3_endofresp() * smtp_endofresp()
* *
* Checks for an ending SMTP status code at the start of the given string, but * Checks for an ending SMTP status code at the start of the given string, but
* also detects various capabilities from the EHLO response including the * also detects various capabilities from the EHLO response including the
@@ -229,80 +231,62 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
{ {
struct smtp_conn *smtpc = &conn->proto.smtpc; struct smtp_conn *smtpc = &conn->proto.smtpc;
bool result = FALSE; bool result = FALSE;
size_t wordlen;
/* Nothing for us */
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2])) if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
return FALSE; /* Nothing for us */ return FALSE;
/* Do we have a command response? */ /* Do we have a command response? This should be the response code followed
result = (line[3] == ' ') ? TRUE : FALSE; by a space and optionally some text as per RFC-5321 and as outlined in
if(result) Section 4. Examples of RFC-4954 but some e-mail servers ignore this and
only send the response code instead as per Section 4.2. */
if(line[3] == ' ' || len == 5) {
result = TRUE;
*resp = curlx_sltosi(strtol(line, NULL, 10)); *resp = curlx_sltosi(strtol(line, NULL, 10));
/* Are we processing EHLO command data? */ /* Make sure real server never sends internal value */
if(smtpc->state == SMTP_EHLO && (!result || (result && *resp/100 == 2))) { if(*resp == 1)
line += 4; *resp = 0;
len -= 4; }
/* Do we have a multiline (continuation) response? */
/* Does the server support the STARTTLS capability? */ else if(line[3] == '-' &&
if(len >= 8 && !memcmp(line, "STARTTLS", 8)) (smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) {
smtpc->tls_supported = TRUE; result = TRUE;
*resp = 1; /* Internal response code */
/* Does the server support the SIZE capability? */
else if(len >= 4 && !memcmp(line, "SIZE", 4))
smtpc->size_supported = TRUE;
/* Do we have the authentication mechanism list? */
else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
line += 5;
len -= 5;
/* Loop through the data line */
for(;;) {
while(len &&
(*line == ' ' || *line == '\t' ||
*line == '\r' || *line == '\n')) {
line++;
len--;
}
if(!len)
break;
/* Extract the word */
for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
line[wordlen] != '\t' && line[wordlen] != '\r' &&
line[wordlen] != '\n';)
wordlen++;
/* Test the word for a matching authentication mechanism */
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
smtpc->authmechs |= SASL_MECH_LOGIN;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
smtpc->authmechs |= SASL_MECH_PLAIN;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
smtpc->authmechs |= SASL_MECH_CRAM_MD5;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
smtpc->authmechs |= SASL_MECH_GSSAPI;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
smtpc->authmechs |= SASL_MECH_EXTERNAL;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
smtpc->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
smtpc->authmechs |= SASL_MECH_XOAUTH2;
line += wordlen;
len -= wordlen;
}
}
} }
return result; return result;
} }
/***********************************************************************
*
* smtp_get_message()
*
* Gets the authentication message from the response buffer.
*/
static void smtp_get_message(char *buffer, char** outptr)
{
size_t len = 0;
char* message = NULL;
/* Find the start of the message */
for(message = buffer + 4; *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()
@@ -330,7 +314,9 @@ static void state(struct connectdata *conn, smtpstate newstate)
"AUTH_NTLM", "AUTH_NTLM",
"AUTH_NTLM_TYPE2MSG", "AUTH_NTLM_TYPE2MSG",
"AUTH_XOAUTH2", "AUTH_XOAUTH2",
"AUTH_CANCEL",
"AUTH_FINAL", "AUTH_FINAL",
"COMMAND",
"MAIL", "MAIL",
"RCPT", "RCPT",
"DATA", "DATA",
@@ -565,6 +551,35 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
return result; return result;
} }
/***********************************************************************
*
* smtp_perform_command()
*
* Sends a SMTP based command.
*/
static CURLcode smtp_perform_command(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->req.protop;
/* Send the command */
if(smtp->rcpt)
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s",
smtp->custom && smtp->custom[0] != '\0' ?
smtp->custom : "VRFY",
smtp->rcpt->data);
else
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
smtp->custom && smtp->custom[0] != '\0' ?
smtp->custom : "HELP");
if(!result)
state(conn, SMTP_COMMAND);
return result;
}
/*********************************************************************** /***********************************************************************
* *
* smtp_perform_mail() * smtp_perform_mail()
@@ -656,16 +671,14 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
struct SMTP *smtp = data->req.protop; struct SMTP *smtp = data->req.protop;
/* Send the RCPT TO command */ /* Send the RCPT TO command */
if(smtp->rcpt) { if(smtp->rcpt->data[0] == '<')
if(smtp->rcpt->data[0] == '<') result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s", smtp->rcpt->data);
smtp->rcpt->data); else
else result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", smtp->rcpt->data);
smtp->rcpt->data); if(!result)
if(!result) state(conn, SMTP_RCPT);
state(conn, SMTP_RCPT);
}
return result; return result;
} }
@@ -740,10 +753,13 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct smtp_conn *smtpc = &conn->proto.smtpc; struct smtp_conn *smtpc = &conn->proto.smtpc;
const char *line = data->state.buffer;
size_t len = strlen(line);
size_t wordlen;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(smtpcode/100 != 2) { if(smtpcode/100 != 2 && smtpcode != 1) {
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) && if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
!conn->bits.user_passwd) !conn->bits.user_passwd)
result = smtp_perform_helo(conn); result = smtp_perform_helo(conn);
@@ -752,21 +768,83 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
result = CURLE_REMOTE_ACCESS_DENIED; result = CURLE_REMOTE_ACCESS_DENIED;
} }
} }
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { else {
/* We don't have a SSL/TLS connection yet, but SSL is requested */ line += 4;
if(smtpc->tls_supported) len -= 4;
/* Switch to TLS connection now */
result = smtp_perform_starttls(conn); /* Does the server support the STARTTLS capability? */
else if(data->set.use_ssl == CURLUSESSL_TRY) if(len >= 8 && !memcmp(line, "STARTTLS", 8))
/* Fallback and carry on with authentication */ smtpc->tls_supported = TRUE;
result = smtp_perform_authenticate(conn);
else { /* Does the server support the SIZE capability? */
failf(data, "STARTTLS not supported."); else if(len >= 4 && !memcmp(line, "SIZE", 4))
result = CURLE_USE_SSL_FAILED; smtpc->size_supported = TRUE;
/* Do we have the authentication mechanism list? */
else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
line += 5;
len -= 5;
/* Loop through the data line */
for(;;) {
while(len &&
(*line == ' ' || *line == '\t' ||
*line == '\r' || *line == '\n')) {
line++;
len--;
}
if(!len)
break;
/* Extract the word */
for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
line[wordlen] != '\t' && line[wordlen] != '\r' &&
line[wordlen] != '\n';)
wordlen++;
/* Test the word for a matching authentication mechanism */
if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
smtpc->authmechs |= SASL_MECH_LOGIN;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
smtpc->authmechs |= SASL_MECH_PLAIN;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
smtpc->authmechs |= SASL_MECH_CRAM_MD5;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
smtpc->authmechs |= SASL_MECH_GSSAPI;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
smtpc->authmechs |= SASL_MECH_EXTERNAL;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
smtpc->authmechs |= SASL_MECH_NTLM;
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
smtpc->authmechs |= SASL_MECH_XOAUTH2;
line += wordlen;
len -= wordlen;
}
}
if(smtpcode != 1) {
if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
result = smtp_perform_starttls(conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
result = smtp_perform_authenticate(conn);
else {
failf(data, "STARTTLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
result = smtp_perform_authenticate(conn);
} }
} }
else
result = smtp_perform_authenticate(conn);
return result; return result;
} }
@@ -811,20 +889,17 @@ static CURLcode smtp_state_auth_plain_resp(struct connectdata *conn,
/* Create the authorisation message */ /* Create the authorisation message */
result = Curl_sasl_create_plain_message(conn->data, conn->user, result = Curl_sasl_create_plain_message(conn->data, conn->user,
conn->passwd, &plainauth, &len); conn->passwd, &plainauth, &len);
if(!result && plainauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
/* Send the message */ if(!result)
if(!result) { state(conn, SMTP_AUTH_FINAL);
if(plainauth) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
if(!result)
state(conn, SMTP_AUTH_FINAL);
}
Curl_safefree(plainauth);
} }
} }
Curl_safefree(plainauth);
return result; return result;
} }
@@ -848,20 +923,17 @@ static CURLcode smtp_state_auth_login_resp(struct connectdata *conn,
/* Create the user message */ /* Create the user message */
result = Curl_sasl_create_login_message(conn->data, conn->user, result = Curl_sasl_create_login_message(conn->data, conn->user,
&authuser, &len); &authuser, &len);
if(!result && authuser) {
/* Send the user */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
/* Send the user */ if(!result)
if(!result) { state(conn, SMTP_AUTH_LOGIN_PASSWD);
if(authuser) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
if(!result)
state(conn, SMTP_AUTH_LOGIN_PASSWD);
}
Curl_safefree(authuser);
} }
} }
Curl_safefree(authuser);
return result; return result;
} }
@@ -885,20 +957,17 @@ static CURLcode smtp_state_auth_login_password_resp(struct connectdata *conn,
/* Create the password message */ /* Create the password message */
result = Curl_sasl_create_login_message(conn->data, conn->passwd, result = Curl_sasl_create_login_message(conn->data, conn->passwd,
&authpasswd, &len); &authpasswd, &len);
if(!result && authpasswd) {
/* Send the password */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
/* Send the password */ if(!result)
if(!result) { state(conn, SMTP_AUTH_FINAL);
if(authpasswd) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
if(!result)
state(conn, SMTP_AUTH_FINAL);
}
Curl_safefree(authpasswd);
} }
} }
Curl_safefree(authpasswd);
return result; return result;
} }
@@ -910,9 +979,10 @@ static CURLcode smtp_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 */
@@ -921,38 +991,34 @@ static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn,
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
/* Get the challenge */ /* Get the challenge message */
for(chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) smtp_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.smtpc.pp, "%s", "*");
break;
if(++len) { if(!result)
chlg64[len] = '\0'; state(conn, SMTP_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.smtpc.pp, "%s", rplyb64); result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
if(!result) if(!result)
state(conn, SMTP_AUTH_FINAL); state(conn, SMTP_AUTH_FINAL);
} }
Curl_safefree(rplyb64);
} }
Curl_safefree(chlg);
Curl_safefree(rplyb64);
return result; return result;
} }
@@ -963,9 +1029,13 @@ static CURLcode smtp_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 */
@@ -974,27 +1044,36 @@ static CURLcode smtp_state_auth_digest_resp(struct connectdata *conn,
return CURLE_LOGIN_DENIED; return CURLE_LOGIN_DENIED;
} }
/* Get the challenge */ /* Get the challenge message */
for(chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++) smtp_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, "smtp", realm, sizeof(realm),
&rplyb64, &len); algorithm, sizeof(algorithm));
if(result || strcmp(algorithm, "md5-sess") != 0) {
/* Send the cancellation */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
/* Send the response */ if(!result)
if(!result) { state(conn, SMTP_AUTH_CANCEL);
if(rplyb64) { }
else {
/* Create the response message */
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
conn->user, conn->passwd,
"smtp", &rplyb64, &len);
if(!result && rplyb64) {
/* Send the response */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
if(!result) if(!result)
state(conn, SMTP_AUTH_DIGESTMD5_RESP); state(conn, SMTP_AUTH_DIGESTMD5_RESP);
} }
Curl_safefree(rplyb64);
} }
Curl_safefree(rplyb64);
return result; return result;
} }
@@ -1047,20 +1126,17 @@ static CURLcode smtp_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.smtpc.pp, "%s", type1msg);
/* Send the message */ if(!result)
if(!result) { state(conn, SMTP_AUTH_NTLM_TYPE2MSG);
if(type1msg) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type1msg);
if(!result)
state(conn, SMTP_AUTH_NTLM_TYPE2MSG);
}
Curl_safefree(type1msg);
} }
} }
Curl_safefree(type1msg);
return result; return result;
} }
@@ -1071,6 +1147,7 @@ static CURLcode smtp_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;
char *type2msg = NULL;
char *type3msg = NULL; char *type3msg = NULL;
size_t len = 0; size_t len = 0;
@@ -1081,26 +1158,35 @@ static CURLcode smtp_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, smtp_get_message(data->state.buffer, &type2msg);
data->state.buffer + 4,
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.smtpc.pp, "%s", "*");
if(!result)
state(conn, SMTP_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.smtpc.pp, "%s", type3msg); result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type3msg);
if(!result) if(!result)
state(conn, SMTP_AUTH_FINAL); state(conn, SMTP_AUTH_FINAL);
} }
Curl_safefree(type3msg);
} }
} }
Curl_safefree(type3msg);
return result; return result;
} }
#endif #endif
@@ -1125,24 +1211,36 @@ static CURLcode smtp_state_auth_xoauth2_resp(struct connectdata *conn,
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user, result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
conn->xoauth2_bearer, conn->xoauth2_bearer,
&xoauth, &len); &xoauth, &len);
if(!result && xoauth) {
/* Send the message */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth);
/* Send the message */ if(!result)
if(!result) { state(conn, SMTP_AUTH_FINAL);
if(xoauth) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth);
if(!result)
state(conn, SMTP_AUTH_FINAL);
}
Curl_safefree(xoauth);
} }
} }
Curl_safefree(xoauth);
return result; return result;
} }
/* For the final responses to the AUTH sequence */ /* For AUTH cancellation responses */
static CURLcode smtp_state_auth_cancel_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
struct SessionHandle *data = conn->data;
(void)smtpcode;
(void)instate; /* no use for this yet */
failf(data, "Authentication cancelled");
return CURLE_LOGIN_DENIED;
}
/* For final responses in the AUTH sequence */
static CURLcode smtp_state_auth_final_resp(struct connectdata *conn, static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
int smtpcode, int smtpcode,
smtpstate instate) smtpstate instate)
@@ -1163,26 +1261,68 @@ static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
return result; return result;
} }
/* For command responses */
static CURLcode smtp_state_command_resp(struct connectdata *conn, int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->req.protop;
char *line = data->state.buffer;
size_t len = strlen(line);
(void)instate; /* no use for this yet */
if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) ||
(!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) {
failf(data, "Command failed: %d", smtpcode);
result = CURLE_RECV_ERROR;
}
else {
/* Temporarily add the LF character back and send as body to the client */
if(!data->set.opt_no_body) {
line[len] = '\n';
result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
}
if(smtpcode != 1) {
if(smtp->rcpt) {
smtp->rcpt = smtp->rcpt->next;
if(smtp->rcpt) {
/* Send the next command */
result = smtp_perform_command(conn);
}
else
/* End of DO phase */
state(conn, SMTP_STOP);
}
else
/* End of DO phase */
state(conn, SMTP_STOP);
}
}
return result;
}
/* For MAIL responses */ /* For MAIL responses */
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode, static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
smtpstate instate) smtpstate instate)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->req.protop;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(smtpcode/100 != 2) { if(smtpcode/100 != 2) {
failf(data, "MAIL failed: %d", smtpcode); failf(data, "MAIL failed: %d", smtpcode);
result = CURLE_SEND_ERROR; result = CURLE_SEND_ERROR;
state(conn, SMTP_STOP);
} }
else { else
smtp->rcpt = data->set.mail_rcpt; /* Start the RCPT TO command */
result = smtp_perform_rcpt_to(conn); result = smtp_perform_rcpt_to(conn);
}
return result; return result;
} }
@@ -1200,23 +1340,20 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
if(smtpcode/100 != 2) { if(smtpcode/100 != 2) {
failf(data, "RCPT failed: %d", smtpcode); failf(data, "RCPT failed: %d", smtpcode);
result = CURLE_SEND_ERROR; result = CURLE_SEND_ERROR;
state(conn, SMTP_STOP);
} }
else { else {
if(smtp->rcpt) { smtp->rcpt = smtp->rcpt->next;
smtp->rcpt = smtp->rcpt->next;
if(smtp->rcpt)
/* Send the next RCPT TO command */
result = smtp_perform_rcpt_to(conn); result = smtp_perform_rcpt_to(conn);
else {
/* Send the DATA command */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
/* If we failed or still are sending RCPT data then return */ if(!result)
if(result || smtp->rcpt) state(conn, SMTP_DATA);
return result;
} }
/* Send the DATA command */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
if(!result)
state(conn, SMTP_DATA);
} }
return result; return result;
@@ -1226,25 +1363,27 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
smtpstate instate) smtpstate instate)
{ {
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */ (void)instate; /* no use for this yet */
if(smtpcode != 354) { if(smtpcode != 354) {
failf(data, "DATA failed: %d", smtpcode);
result = CURLE_SEND_ERROR;
}
else {
/* Set the progress upload size */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
/* SMTP upload */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
/* End of DO phase */
state(conn, SMTP_STOP); state(conn, SMTP_STOP);
return CURLE_SEND_ERROR;
} }
/* Set the progress upload size */ return result;
Curl_pgrsSetUploadSize(data, data->set.infilesize);
/* SMTP upload */
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
/* End of DO phase */
state(conn, SMTP_STOP);
return CURLE_OK;
} }
/* For POSTDATA responses, which are received after the entire DATA /* For POSTDATA responses, which are received after the entire DATA
@@ -1284,16 +1423,19 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
if(pp->sendleft) if(pp->sendleft)
return Curl_pp_flushsend(pp); return Curl_pp_flushsend(pp);
/* Read the response from the server */ do {
result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); /* Read the response from the server */
if(result) result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
return result; if(result)
return result;
/* Store the latest response for later retrieval */ /* Store the latest response for later retrieval if necessary */
if(smtpc->state != SMTP_QUIT) if(smtpc->state != SMTP_QUIT && smtpcode != 1)
data->info.httpcode = smtpcode; data->info.httpcode = smtpcode;
if(!smtpcode)
break;
if(smtpcode) {
/* We have now received a full SMTP server response */ /* We have now received a full SMTP server response */
switch(smtpc->state) { switch(smtpc->state) {
case SMTP_SERVERGREET: case SMTP_SERVERGREET:
@@ -1354,10 +1496,18 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state); result = smtp_state_auth_xoauth2_resp(conn, smtpcode, smtpc->state);
break; break;
case SMTP_AUTH_CANCEL:
result = smtp_state_auth_cancel_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_AUTH_FINAL: case SMTP_AUTH_FINAL:
result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state); result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
break; break;
case SMTP_COMMAND:
result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_MAIL: case SMTP_MAIL:
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
break; break;
@@ -1381,7 +1531,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
state(conn, SMTP_STOP); state(conn, SMTP_STOP);
break; break;
} }
} } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
return result; return result;
} }
@@ -1521,7 +1671,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
conn->bits.close = TRUE; /* marked for closure */ conn->bits.close = TRUE; /* marked for closure */
result = status; /* use the already set error code */ result = status; /* use the already set error code */
} }
else if(!data->set.connect_only) { else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
/* Calculate the EOB taking into account any terminating CRLF from the /* Calculate the EOB taking into account any terminating CRLF from the
previous line of the email or the CRLF of the DATA command when there previous line of the email or the CRLF of the DATA command when there
is "no mail data". RFC-5321, sect. 4.1.1.4. */ is "no mail data". RFC-5321, sect. 4.1.1.4. */
@@ -1560,6 +1710,9 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
result = smtp_block_statemach(conn); result = smtp_block_statemach(conn);
} }
/* Cleanup our per-request based variables */
Curl_safefree(smtp->custom);
/* Clear the transfer mode for the next request */ /* Clear the transfer mode for the next request */
smtp->transfer = FTPTRANSFER_BODY; smtp->transfer = FTPTRANSFER_BODY;
@@ -1570,31 +1723,41 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
* *
* smtp_perform() * smtp_perform()
* *
* This is the actual DO function for SMTP. Send a mail according to the * This is the actual DO function for SMTP. Transfer a mail, send a command
* options previously setup. * or get some data according to the options previously setup.
*/ */
static CURLcode smtp_perform(struct connectdata *conn, bool *connected, static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
bool *dophase_done) bool *dophase_done)
{ {
/* This is SMTP and no proxy */ /* This is SMTP and no proxy */
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = 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(data->set.opt_no_body) {
/* Requested no body means no transfer */ /* Requested no body means no transfer */
struct SMTP *smtp = conn->data->req.protop;
smtp->transfer = FTPTRANSFER_INFO; smtp->transfer = FTPTRANSFER_INFO;
} }
*dophase_done = FALSE; /* not done yet */ *dophase_done = FALSE; /* not done yet */
/* Store the first recipient (or NULL if not specified) */
smtp->rcpt = data->set.mail_rcpt;
/* Start the first command in the DO phase */ /* Start the first command in the DO phase */
result = smtp_perform_mail(conn); if(data->set.upload && data->set.mail_rcpt)
/* MAIL transfer */
result = smtp_perform_mail(conn);
else
/* SMTP based command (VRFY, EXPN, NOOP, RSET or HELP) */
result = smtp_perform_command(conn);
if(result) if(result)
return result; return result;
/* run the state-machine */ /* Run the state-machine */
result = smtp_multi_statemach(conn, dophase_done); result = smtp_multi_statemach(conn, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET]; *connected = conn->bits.tcpconnect[FIRSTSOCKET];
@@ -1620,6 +1783,11 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
*done = FALSE; /* default to false */ *done = FALSE; /* default to false */
/* Parse the custom request */
result = smtp_parse_custom_request(conn);
if(result)
return result;
result = smtp_regular_transfer(conn, done); result = smtp_regular_transfer(conn, done);
return result; return result;
@@ -1632,8 +1800,7 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
* Disconnect from an SMTP server. Cleanup protocol-specific per-connection * Disconnect from an SMTP server. Cleanup protocol-specific per-connection
* resources. BLOCKING. * resources. BLOCKING.
*/ */
static CURLcode smtp_disconnect(struct connectdata *conn, static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
bool dead_connection)
{ {
struct smtp_conn *smtpc = &conn->proto.smtpc; struct smtp_conn *smtpc = &conn->proto.smtpc;
@@ -1643,7 +1810,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn,
/* The SMTP session may or may not have been allocated/setup at this /* The SMTP session may or may not have been allocated/setup at this
point! */ point! */
if(!dead_connection && smtpc->pp.conn) if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
if(!smtp_perform_quit(conn)) if(!smtp_perform_quit(conn))
(void)smtp_block_statemach(conn); /* ignore errors on QUIT */ (void)smtp_block_statemach(conn); /* ignore errors on QUIT */
@@ -1836,6 +2003,26 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE); return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
} }
/***********************************************************************
*
* smtp_parse_custom_request()
*
* Parse the custom request.
*/
static CURLcode smtp_parse_custom_request(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct SMTP *smtp = data->req.protop;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
/* URL decode the custom request */
if(custom)
result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
return result;
}
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread) CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
{ {
/* When sending a SMTP payload we must detect CRLF. sequences making sure /* When sending a SMTP payload we must detect CRLF. sequences making sure

View File

@@ -45,7 +45,9 @@ typedef enum {
SMTP_AUTH_NTLM, SMTP_AUTH_NTLM,
SMTP_AUTH_NTLM_TYPE2MSG, SMTP_AUTH_NTLM_TYPE2MSG,
SMTP_AUTH_XOAUTH2, 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,
@@ -60,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 */
} }

View File

@@ -754,7 +754,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
curlx_uztoui(strlen(conn->user))); curlx_uztoui(strlen(conn->user)));
if(!sshc->authlist) { if(!sshc->authlist) {
if((err = libssh2_session_last_errno(sshc->ssh_session)) == if(libssh2_userauth_authenticated(sshc->ssh_session)) {
sshc->authed = TRUE;
infof(data, "SSH user accepted with no authentication\n");
state(conn, SSH_AUTH_DONE);
break;
}
else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
rc = LIBSSH2_ERROR_EAGAIN; rc = LIBSSH2_ERROR_EAGAIN;
break; break;
@@ -2719,6 +2725,10 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
CURLcode result; CURLcode result;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
/* initialize per-handle data if not already */
if(!data->req.protop)
ssh_setup_connection(conn);
/* We default to persistent connections. We set this already in this connect /* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */ function to make the re-use checks properly be able to check this bit. */
conn->bits.close = FALSE; conn->bits.close = FALSE;

View File

@@ -611,6 +611,9 @@ int Curl_ssl_init_certinfo(struct SessionHandle * data,
return 0; return 0;
} }
/*
* 'value' is NOT a zero terminated string
*/
CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data, CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
int certnum, int certnum,
const char *label, const char *label,
@@ -621,12 +624,22 @@ CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
char * output; char * output;
struct curl_slist * nl; struct curl_slist * nl;
CURLcode res = CURLE_OK; CURLcode res = CURLE_OK;
size_t labellen = strlen(label);
size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
/* Add an information record for a particular certificate. */ output = malloc(outlen);
output = curl_maprintf("%s:%.*s", label, valuelen, value);
if(!output) if(!output)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* sprintf the label and colon */
snprintf(output, outlen, "%s:", label);
/* memcpy the value (it might not be zero terminated) */
memcpy(&output[labellen+1], value, valuelen);
/* zero terminate the output */
output[labellen + 1 + valuelen] = 0;
nl = Curl_slist_append_nodup(ci->certinfo[certnum], output); nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
if(!nl) { if(!nl) {
free(output); free(output);

View File

@@ -1431,19 +1431,12 @@ ossl_connect_step1(struct connectdata *conn,
switch(data->set.ssl.version) { switch(data->set.ssl.version) {
default: default:
case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_DEFAULT:
#ifdef USE_TLS_SRP
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
infof(data, "Set version TLSv1 for SRP authorisation\n");
req_method = TLSv1_client_method() ;
}
else
#endif
/* we try to figure out version */
req_method = SSLv23_client_method();
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1:
req_method = TLSv1_client_method(); case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
/* it will be handled later with the context options */
req_method = SSLv23_client_method();
use_sni(TRUE); use_sni(TRUE);
break; break;
case CURL_SSLVERSION_SSLv2: case CURL_SSLVERSION_SSLv2:
@@ -1556,9 +1549,51 @@ ossl_connect_step1(struct connectdata *conn,
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif #endif
/* disable SSLv2 in the default case (i.e. allow SSLv3 and TLSv1) */ switch(data->set.ssl.version) {
if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT) case CURL_SSLVERSION_DEFAULT:
ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_SSLv2;
#ifdef USE_TLS_SRP
if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
infof(data, "Set version TLSv1.x for SRP authorisation\n");
ctx_options |= SSL_OP_NO_SSLv3;
}
#endif
break;
case CURL_SSLVERSION_TLSv1:
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
break;
case CURL_SSLVERSION_TLSv1_0:
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
ctx_options |= SSL_OP_NO_TLSv1_1;
ctx_options |= SSL_OP_NO_TLSv1_2;
#endif
break;
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
case CURL_SSLVERSION_TLSv1_1:
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
ctx_options |= SSL_OP_NO_TLSv1;
ctx_options |= SSL_OP_NO_TLSv1_2;
break;
case CURL_SSLVERSION_TLSv1_2:
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
ctx_options |= SSL_OP_NO_TLSv1;
ctx_options |= SSL_OP_NO_TLSv1_1;
break;
#endif
default:
failf(data, "Unsupported SSL protocol version");
return CURLE_SSL_CONNECT_ERROR;
}
SSL_CTX_set_options(connssl->ctx, ctx_options); SSL_CTX_set_options(connssl->ctx, ctx_options);

View File

@@ -1256,7 +1256,7 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
if(*dophase_done) { if(*dophase_done) {
DEBUGF(infof(conn->data, "DO phase is complete\n")); DEBUGF(infof(conn->data, "DO phase is complete\n"));
} }
else { else if(!result) {
/* The multi code doesn't have this logic for the DOING state so we /* The multi code doesn't have this logic for the DOING state so we
provide it for TFTP since it may do the entire transfer in this provide it for TFTP since it may do the entire transfer in this
state. */ state. */

View File

@@ -1309,10 +1309,11 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
Curl_pgrsStartNow(data); Curl_pgrsStartNow(data);
if(data->set.timeout) if(data->set.timeout)
Curl_expire(data, data->set.timeout); Curl_expire(data, data->set.timeout + MULTI_TIMEOUT_INACCURACY_MS);
if(data->set.connecttimeout) if(data->set.connecttimeout)
Curl_expire(data, data->set.connecttimeout); Curl_expire(data, data->set.connecttimeout +
MULTI_TIMEOUT_INACCURACY_MS);
/* In case the handle is re-used and an authentication method was picked /* In case the handle is re-used and an authentication method was picked
in the session we need to make sure we only use the one(s) we now in the session we need to make sure we only use the one(s) we now

152
lib/url.c
View File

@@ -299,13 +299,11 @@ static CURLcode setstropt(char **charp, char *s)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp, static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
char **optionsp)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
char *user = NULL; char *user = NULL;
char *passwd = NULL; char *passwd = NULL;
char *options = NULL;
/* Parse the login details if specified. It not then we treat NULL as a hint /* Parse the login details if specified. It not then we treat NULL as a hint
to clear the existing data */ to clear the existing data */
@@ -313,7 +311,7 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
result = parse_login_details(option, strlen(option), result = parse_login_details(option, strlen(option),
(userp ? &user : NULL), (userp ? &user : NULL),
(passwdp ? &passwd : NULL), (passwdp ? &passwd : NULL),
(optionsp ? &options : NULL)); NULL);
} }
if(!result) { if(!result) {
@@ -335,12 +333,6 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
Curl_safefree(*passwdp); Curl_safefree(*passwdp);
*passwdp = passwd; *passwdp = passwd;
} }
/* Store the options part of option if required */
if(optionsp) {
Curl_safefree(*optionsp);
*optionsp = options;
}
} }
return result; return result;
@@ -1553,13 +1545,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
case CURLOPT_USERPWD: case CURLOPT_USERPWD:
/* /*
* user:password;options to use in the operation * user:password to use in the operation
*/ */
result = setstropt_userpwd(va_arg(param, char *), result = setstropt_userpwd(va_arg(param, char *),
&data->set.str[STRING_USERNAME], &data->set.str[STRING_USERNAME],
&data->set.str[STRING_PASSWORD], &data->set.str[STRING_PASSWORD]);
&data->set.str[STRING_OPTIONS]);
break; break;
case CURLOPT_USERNAME: case CURLOPT_USERNAME:
/* /*
* authentication user name to use in the operation * authentication user name to use in the operation
@@ -1567,6 +1559,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
result = setstropt(&data->set.str[STRING_USERNAME], result = setstropt(&data->set.str[STRING_USERNAME],
va_arg(param, char *)); va_arg(param, char *));
break; break;
case CURLOPT_PASSWORD: case CURLOPT_PASSWORD:
/* /*
* authentication password to use in the operation * authentication password to use in the operation
@@ -1574,6 +1567,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
result = setstropt(&data->set.str[STRING_PASSWORD], result = setstropt(&data->set.str[STRING_PASSWORD],
va_arg(param, char *)); va_arg(param, char *));
break; break;
case CURLOPT_LOGIN_OPTIONS:
/*
* authentication options to use in the operation
*/
result = setstropt(&data->set.str[STRING_OPTIONS],
va_arg(param, char *));
break;
case CURLOPT_XOAUTH2_BEARER: case CURLOPT_XOAUTH2_BEARER:
/* /*
* XOAUTH2 bearer token to use in the operation * XOAUTH2 bearer token to use in the operation
@@ -1581,6 +1583,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
result = setstropt(&data->set.str[STRING_BEARER], result = setstropt(&data->set.str[STRING_BEARER],
va_arg(param, char *)); va_arg(param, char *));
break; break;
case CURLOPT_POSTQUOTE: case CURLOPT_POSTQUOTE:
/* /*
* List of RAW FTP commands to use after a transfer * List of RAW FTP commands to use after a transfer
@@ -1650,7 +1653,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*/ */
result = setstropt_userpwd(va_arg(param, char *), result = setstropt_userpwd(va_arg(param, char *),
&data->set.str[STRING_PROXYUSERNAME], &data->set.str[STRING_PROXYUSERNAME],
&data->set.str[STRING_PROXYPASSWORD], NULL); &data->set.str[STRING_PROXYPASSWORD]);
break; break;
case CURLOPT_PROXYUSERNAME: case CURLOPT_PROXYUSERNAME:
/* /*
@@ -1926,7 +1929,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ssl.fsslctxp = va_arg(param, void *); data->set.ssl.fsslctxp = va_arg(param, void *);
break; break;
#endif #endif
#if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT) #if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT) || \
defined(USE_NSS)
case CURLOPT_CERTINFO: case CURLOPT_CERTINFO:
data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE; data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
break; break;
@@ -2502,6 +2506,10 @@ static void conn_free(struct connectdata *conn)
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
if(CURL_SOCKET_BAD != conn->tempsock[0])
Curl_closesocket(conn, conn->tempsock[0]);
if(CURL_SOCKET_BAD != conn->tempsock[1])
Curl_closesocket(conn, conn->tempsock[1]);
#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
Curl_ntlm_wb_cleanup(conn); Curl_ntlm_wb_cleanup(conn);
@@ -3219,9 +3227,12 @@ static CURLcode ConnectionStore(struct SessionHandle *data,
Note: this function's sub-functions call failf() Note: this function's sub-functions call failf()
*/ */
CURLcode Curl_connected_proxy(struct connectdata *conn) CURLcode Curl_connected_proxy(struct connectdata *conn,
int sockindex)
{ {
if(!conn->bits.proxy) if(!conn->bits.proxy || sockindex)
/* this magic only works for the primary socket as the secondary is used
for FTP only and it has FTP specific magic in ftp.c */
return CURLE_OK; return CURLE_OK;
switch(conn->proxytype) { switch(conn->proxytype) {
@@ -3252,49 +3263,6 @@ CURLcode Curl_connected_proxy(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
static CURLcode ConnectPlease(struct SessionHandle *data,
struct connectdata *conn,
bool *connected)
{
CURLcode result;
Curl_addrinfo *addr;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
char *hostname = conn->bits.proxy?conn->proxy.name:conn->host.name;
infof(data, "About to connect() to %s%s port %ld (#%ld)\n",
conn->bits.proxy?"proxy ":"",
hostname, conn->port, conn->connection_id);
#else
(void)data;
#endif
/*************************************************************
* Connect to server/proxy
*************************************************************/
result= Curl_connecthost(conn,
conn->dns_entry,
&conn->sock[FIRSTSOCKET],
&addr,
connected);
if(CURLE_OK == result) {
/* All is cool, we store the current information */
conn->ip_addr = addr;
if(*connected) {
result = Curl_connected_proxy(conn);
if(!result) {
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
}
}
}
if(result)
*connected = FALSE; /* mark it as not connected */
return result;
}
/* /*
* verboseconnect() displays verbose information after a connect * verboseconnect() displays verbose information after a connect
*/ */
@@ -3561,6 +3529,8 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */ conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
conn->connection_id = -1; /* no ID */ conn->connection_id = -1; /* no ID */
conn->port = -1; /* unknown at this point */ conn->port = -1; /* unknown at this point */
@@ -4857,7 +4827,7 @@ static CURLcode override_login(struct SessionHandle *data,
} }
/* /*
* Set password so it's available in the connection. * Set the login details so they're available in the connection
*/ */
static CURLcode set_login(struct connectdata *conn, static CURLcode set_login(struct connectdata *conn,
const char *user, const char *passwd, const char *user, const char *passwd,
@@ -5598,53 +5568,19 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
is later set again for the progress meter purpose */ is later set again for the progress meter purpose */
conn->now = Curl_tvnow(); conn->now = Curl_tvnow();
for(;;) { if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
/* loop for CURL_SERVER_CLOSED_CONNECTION */ conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
result = Curl_connecthost(conn, conn->dns_entry);
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) { if(result)
/* Try to connect only if not already connected */ return result;
bool connected = FALSE; }
else {
result = ConnectPlease(data, conn, &connected); Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
if(result && !conn->ip_addr) { conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
/* transport connection failure not related with authentication */ *protocol_done = TRUE;
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE; Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
return result; Curl_verboseconnect(conn);
}
if(connected) {
result = Curl_protocol_connect(conn, protocol_done);
if(CURLE_OK == result)
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
}
else
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
/* if the connection was closed by the server while exchanging
authentication informations, retry with the new set
authentication information */
if(conn->bits.proxy_connect_closed) {
/* reset the error buffer */
if(data->set.errorbuffer)
data->set.errorbuffer[0] = '\0';
data->state.errorbuf = FALSE;
continue;
}
if(CURLE_OK != result)
return result;
}
else {
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
*protocol_done = TRUE;
Curl_verboseconnect(conn);
Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
}
/* Stop the loop now */
break;
} }
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we conn->now = Curl_tvnow(); /* time this *after* the connect is done, we

View File

@@ -70,7 +70,7 @@ void Curl_close_connections(struct SessionHandle *data);
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
service */ service */
CURLcode Curl_connected_proxy(struct connectdata *conn); CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
#ifdef CURL_DISABLE_VERBOSE_STRINGS #ifdef CURL_DISABLE_VERBOSE_STRINGS
#define Curl_verboseconnect(x) Curl_nop_stmt #define Curl_verboseconnect(x) Curl_nop_stmt

View File

@@ -838,6 +838,7 @@ struct connectdata {
within the DNS cache, so this pointer is only valid as long as the DNS within the DNS cache, so this pointer is only valid as long as the DNS
cache entry remains locked. It gets unlocked in Curl_done() */ cache entry remains locked. It gets unlocked in Curl_done() */
Curl_addrinfo *ip_addr; Curl_addrinfo *ip_addr;
Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
/* 'ip_addr_str' is the ip_addr data as a human readable string. /* 'ip_addr_str' is the ip_addr data as a human readable string.
It remains available as long as the connection does, which is longer than It remains available as long as the connection does, which is longer than
@@ -889,6 +890,7 @@ struct connectdata {
struct timeval created; /* creation time */ struct timeval created; /* creation time */
curl_socket_t sock[2]; /* two sockets, the second is used for the data curl_socket_t sock[2]; /* two sockets, the second is used for the data
transfer when doing FTP */ transfer when doing FTP */
curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */
bool sock_accepted[2]; /* TRUE if the socket on this index was created with bool sock_accepted[2]; /* TRUE if the socket on this index was created with
accept() */ accept() */
Curl_recv *recv[2]; Curl_recv *recv[2];
@@ -1635,6 +1637,8 @@ struct SessionHandle {
other dynamic purposes */ other dynamic purposes */
struct WildcardData wildcard; /* wildcard download state info */ struct WildcardData wildcard; /* wildcard download state info */
struct PureInfo info; /* stats, reports and info data */ struct PureInfo info; /* stats, reports and info data */
struct curl_tlssessioninfo tsi; /* Information about the TLS session, only
valid after a client has asked for it */
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
iconv_t outbound_cd; /* for translating to the network encoding */ iconv_t outbound_cd; /* for translating to the network encoding */
iconv_t inbound_cd; /* for translating from the network encoding */ iconv_t inbound_cd; /* for translating from the network encoding */

View File

@@ -22,7 +22,7 @@
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_QSOSSL) || defined(USE_GSKIT) #if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
#include <curl/curl.h> #include <curl/curl.h>
#include "urldata.h" #include "urldata.h"
@@ -252,7 +252,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
size_t inlength = end - from; size_t inlength = end - from;
int size = 1; int size = 1;
size_t outlength; size_t outlength;
int chsize; int charsize;
unsigned int wc; unsigned int wc;
char * buf; char * buf;
@@ -305,7 +305,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
default: /* case 1: */ default: /* case 1: */
wc = (wc << 8) | *(const unsigned char *) from++; wc = (wc << 8) | *(const unsigned char *) from++;
} }
chsize = 1; charsize = 1;
if(wc >= 0x00000080) { if(wc >= 0x00000080) {
if(wc >= 0x00000800) { if(wc >= 0x00000800) {
if(wc >= 0x00010000) { if(wc >= 0x00010000) {
@@ -315,18 +315,18 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
} }
buf[outlength + 3] = (char) (0x80 | (wc & 0x3F)); buf[outlength + 3] = (char) (0x80 | (wc & 0x3F));
wc = (wc >> 6) | 0x00010000; wc = (wc >> 6) | 0x00010000;
chsize++; charsize++;
} }
buf[outlength + 2] = (char) (0x80 | (wc & 0x3F)); buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
wc = (wc >> 6) | 0x00000800; wc = (wc >> 6) | 0x00000800;
chsize++; charsize++;
} }
buf[outlength + 1] = (char) (0x80 | (wc & 0x3F)); buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
wc = (wc >> 6) | 0x000000C0; wc = (wc >> 6) | 0x000000C0;
chsize++; charsize++;
} }
buf[outlength] = (char) wc; buf[outlength] = (char) wc;
outlength += chsize; outlength += charsize;
} }
} }
buf[outlength] = '\0'; buf[outlength] = '\0';
@@ -803,7 +803,7 @@ static const char * dumpAlgo(curl_asn1Element * param,
return OID2str(oid.beg, oid.end, TRUE); return OID2str(oid.beg, oid.end, TRUE);
} }
static void do_pubkey_field(struct SessionHandle *data, int certnum, static void do_pubkey_field(struct SessionHandle * data, int certnum,
const char * label, curl_asn1Element * elem) const char * label, curl_asn1Element * elem)
{ {
const char * output; const char * output;
@@ -812,8 +812,10 @@ static void do_pubkey_field(struct SessionHandle *data, int certnum,
output = Curl_ASN1tostr(elem, 0); output = Curl_ASN1tostr(elem, 0);
if(output) { if(output) {
Curl_ssl_push_certinfo(data, certnum, label, output); if(data->set.ssl.certinfo)
infof(data, " %s: %s\n", label, output); Curl_ssl_push_certinfo(data, certnum, label, output);
if(!certnum)
infof(data, " %s: %s\n", label, output);
free((char *) output); free((char *) output);
} }
} }
@@ -845,11 +847,14 @@ static void do_pubkey(struct SessionHandle * data, int certnum,
len--; len--;
if(len > 32) if(len > 32)
elem.beg = q; /* Strip leading zero bytes. */ elem.beg = q; /* Strip leading zero bytes. */
infof(data, " RSA Public Key (%lu bits)\n", len); if(!certnum)
q = curl_maprintf("%lu", len); infof(data, " RSA Public Key (%lu bits)\n", len);
if(q) { if(data->set.ssl.certinfo) {
Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q); q = curl_maprintf("%lu", len);
free((char *) q); if(q) {
Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
free((char *) q);
}
} }
/* Generate coefficients. */ /* Generate coefficients. */
do_pubkey_field(data, certnum, "rsa(n)", &elem); do_pubkey_field(data, certnum, "rsa(n)", &elem);
@@ -896,6 +901,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
size_t i; size_t i;
size_t j; size_t j;
if(!data->set.ssl.certinfo)
if(certnum)
return CURLE_OK;
/* Prepare the certificate information for curl_easy_getinfo(). */ /* Prepare the certificate information for curl_easy_getinfo(). */
/* Extract the certificate ASN.1 elements. */ /* Extract the certificate ASN.1 elements. */
@@ -905,35 +914,44 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
ccp = Curl_DNtostr(&cert.subject); ccp = Curl_DNtostr(&cert.subject);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Subject", ccp); if(data->set.ssl.certinfo)
infof(data, "%2d Subject: %s\n", certnum, ccp); Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
if(!certnum)
infof(data, "%2d Subject: %s\n", certnum, ccp);
free((char *) ccp); free((char *) ccp);
/* Issuer. */ /* Issuer. */
ccp = Curl_DNtostr(&cert.issuer); ccp = Curl_DNtostr(&cert.issuer);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp); if(data->set.ssl.certinfo)
infof(data, " Issuer: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
if(!certnum)
infof(data, " Issuer: %s\n", ccp);
free((char *) ccp); free((char *) ccp);
/* Version (always fits in less than 32 bits). */ /* Version (always fits in less than 32 bits). */
version = 0; version = 0;
for(ccp = cert.version.beg; ccp < cert.version.end; ccp++) for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
version = (version << 8) | *(const unsigned char *) ccp; version = (version << 8) | *(const unsigned char *) ccp;
ccp = curl_maprintf("%lx", version); if(data->set.ssl.certinfo) {
if(!ccp) ccp = curl_maprintf("%lx", version);
return CURLE_OUT_OF_MEMORY; if(!ccp)
Curl_ssl_push_certinfo(data, certnum, "Version", ccp); return CURLE_OUT_OF_MEMORY;
free((char *) ccp); Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
infof(data, " Version: %lu (0x%lx)\n", version + 1, version); free((char *) ccp);
}
if(!certnum)
infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
/* Serial number. */ /* Serial number. */
ccp = Curl_ASN1tostr(&cert.serialNumber, 0); ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp); if(data->set.ssl.certinfo)
infof(data, " Serial Number: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
if(!certnum)
infof(data, " Serial Number: %s\n", ccp);
free((char *) ccp); free((char *) ccp);
/* Signature algorithm .*/ /* Signature algorithm .*/
@@ -941,24 +959,30 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
cert.signatureAlgorithm.end); cert.signatureAlgorithm.end);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp); if(data->set.ssl.certinfo)
infof(data, " Signature Algorithm: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
if(!certnum)
infof(data, " Signature Algorithm: %s\n", ccp);
free((char *) ccp); free((char *) ccp);
/* Start Date. */ /* Start Date. */
ccp = Curl_ASN1tostr(&cert.notBefore, 0); ccp = Curl_ASN1tostr(&cert.notBefore, 0);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp); if(data->set.ssl.certinfo)
infof(data, " Start Date: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
if(!certnum)
infof(data, " Start Date: %s\n", ccp);
free((char *) ccp); free((char *) ccp);
/* Expire Date. */ /* Expire Date. */
ccp = Curl_ASN1tostr(&cert.notAfter, 0); ccp = Curl_ASN1tostr(&cert.notAfter, 0);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp); if(data->set.ssl.certinfo)
infof(data, " Expire Date: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
if(!certnum)
infof(data, " Expire Date: %s\n", ccp);
free((char *) ccp); free((char *) ccp);
/* Public Key Algorithm. */ /* Public Key Algorithm. */
@@ -966,8 +990,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
cert.subjectPublicKeyAlgorithm.end); cert.subjectPublicKeyAlgorithm.end);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp); if(data->set.ssl.certinfo)
infof(data, " Public Key Algorithm: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
if(!certnum)
infof(data, " Public Key Algorithm: %s\n", ccp);
do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey); do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey);
free((char *) ccp); free((char *) ccp);
@@ -977,8 +1003,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
ccp = Curl_ASN1tostr(&cert.signature, 0); ccp = Curl_ASN1tostr(&cert.signature, 0);
if(!ccp) if(!ccp)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
Curl_ssl_push_certinfo(data, certnum, "Signature", ccp); if(data->set.ssl.certinfo)
infof(data, " Signature: %s\n", ccp); Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
if(!certnum)
infof(data, " Signature: %s\n", ccp);
free((char *) ccp); free((char *) ccp);
/* Generate PEM certificate. */ /* Generate PEM certificate. */
@@ -987,7 +1015,7 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
&cp1, &cl1); &cp1, &cl1);
if(cc != CURLE_OK) if(cc != CURLE_OK)
return cc; return cc;
/* Compute the number of charaters in final certificate string. Format is: /* Compute the number of characters in final certificate string. Format is:
-----BEGIN CERTIFICATE-----\n -----BEGIN CERTIFICATE-----\n
<max 64 base64 characters>\n <max 64 base64 characters>\n
. .
@@ -1008,8 +1036,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
i += copySubstring(cp2 + i, "-----END CERTIFICATE-----"); i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
cp2[i] = '\0'; cp2[i] = '\0';
free(cp1); free(cp1);
Curl_ssl_push_certinfo(data, certnum, "Cert", cp2); if(data->set.ssl.certinfo)
infof(data, "%s\n", cp2); Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
if(!certnum)
infof(data, "%s\n", cp2);
free(cp2); free(cp2);
return CURLE_OK; return CURLE_OK;
} }
@@ -1148,4 +1178,4 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
return CURLE_PEER_FAILED_VERIFICATION; return CURLE_PEER_FAILED_VERIFICATION;
} }
#endif /* USE_QSOSSL or USE_GSKIT */ #endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */

View File

@@ -25,7 +25,7 @@
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_QSOSSL) || defined(USE_GSKIT) #if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
#include "urldata.h" #include "urldata.h"
@@ -125,5 +125,5 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
CURLcode Curl_verifyhost(struct connectdata * conn, CURLcode Curl_verifyhost(struct connectdata * conn,
const char * beg, const char * end); const char * beg, const char * end);
#endif /* USE_QSOSSL or USE_GSKIT */ #endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
#endif /* HEADER_CURL_X509ASN1_H */ #endif /* HEADER_CURL_X509ASN1_H */

View File

@@ -85,6 +85,7 @@ options:
CURLOPT_ISSUERCERT CURLOPT_ISSUERCERT
CURLOPT_KEYPASSWD CURLOPT_KEYPASSWD
CURLOPT_KRBLEVEL CURLOPT_KRBLEVEL
CURLOPT_LOGIN_OPTIONS
CURLOPT_MAIL_FROM CURLOPT_MAIL_FROM
CURLOPT_MAIL_AUTH CURLOPT_MAIL_AUTH
CURLOPT_NETRC_FILE CURLOPT_NETRC_FILE
@@ -118,6 +119,7 @@ options:
CURLOPT_USERAGENT CURLOPT_USERAGENT
CURLOPT_USERNAME CURLOPT_USERNAME
CURLOPT_USERPWD CURLOPT_USERPWD
CURLOPT_XOAUTH2_BEARER
Else it is the same as for curl_easy_setopt(). Else it is the same as for curl_easy_setopt().
Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the
address of an (empty) character buffer, not the address of a string. address of an (empty) character buffer, not the address of a string.

View File

@@ -77,7 +77,8 @@ makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
static iconv_t static iconv_t
iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, unsigned int cstr) iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin,
unsigned int cstr)
{ {
char fromcode[ICONV_ID_SIZE]; char fromcode[ICONV_ID_SIZE];
@@ -218,7 +219,7 @@ slist_convert(int dccsid, struct curl_slist * from, int sccsid)
struct curl_slist * to = (struct curl_slist *) NULL; struct curl_slist * to = (struct curl_slist *) NULL;
char * cp; char * cp;
for (; from; from = from->next) { for(; from; from = from->next) {
if(!(cp = dynconvert(dccsid, from->data, -1, sccsid))) { if(!(cp = dynconvert(dccsid, from->data, -1, sccsid))) {
curl_slist_free_all(to); curl_slist_free_all(to);
return (struct curl_slist *) NULL; return (struct curl_slist *) NULL;
@@ -407,7 +408,7 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
compiler seems to compare string values after substitution. */ compiler seems to compare string values after substitution. */
#if CURLVERSION_NOW != CURLVERSION_FOURTH #if CURLVERSION_NOW != CURLVERSION_FOURTH
#error curl_version_info_data structure has changed: upgrade this procedure too. #error curl_version_info_data structure has changed: upgrade this procedure.
#endif #endif
/* If caller has been compiled with a new version, error. */ /* If caller has been compiled with a new version, error. */
@@ -426,7 +427,7 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
nproto = 0; nproto = 0;
if(p->protocols) { if(p->protocols) {
while (p->protocols[nproto]) while(p->protocols[nproto])
n += strlen(p->protocols[nproto++]); n += strlen(p->protocols[nproto++]);
n += nproto++; n += nproto++;
@@ -478,7 +479,7 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
cp += i; cp += i;
n -= i; n -= i;
for (i = 0; id->protocols[i]; i++) for(i = 0; id->protocols[i]; i++)
if(convert_version_info_string(((const char * *) id->protocols) + i, if(convert_version_info_string(((const char * *) id->protocols) + i,
&cp, &n, ccsid)) &cp, &n, ccsid))
return (curl_version_info_data *) NULL; return (curl_version_info_data *) NULL;
@@ -593,7 +594,7 @@ curl_certinfo_free_all(struct curl_certinfo *info)
/* Free all memory used by certificate info. */ /* Free all memory used by certificate info. */
if(info) { if(info) {
if(info->certinfo) { if(info->certinfo) {
for (i = 0; i < info->num_of_certs; i++) for(i = 0; i < info->num_of_certs; i++)
curl_slist_free_all(info->certinfo[i]); curl_slist_free_all(info->certinfo[i]);
free((char *) info->certinfo); free((char *) info->certinfo);
} }
@@ -647,19 +648,21 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
case CURLINFO_SLIST: case CURLINFO_SLIST:
ccsid = va_arg(arg, unsigned int); ccsid = va_arg(arg, unsigned int);
if(info == CURLINFO_CERTINFO) { switch (info) {
case CURLINFO_CERTINFO:
cipf = *(struct curl_certinfo * *) paramp; cipf = *(struct curl_certinfo * *) paramp;
if(cipf) { if(cipf) {
if(!(cipt = (struct curl_certinfo *) malloc(sizeof *cipt))) if(!(cipt = (struct curl_certinfo *) malloc(sizeof *cipt)))
ret = CURLE_OUT_OF_MEMORY; ret = CURLE_OUT_OF_MEMORY;
else { else {
cipt->certinfo = (struct curl_slist * *) calloc(cipf->num_of_certs + cipt->certinfo = (struct curl_slist * *)
1, sizeof(struct curl_slist *)); calloc(cipf->num_of_certs +
1, sizeof(struct curl_slist *));
if(!cipt->certinfo) if(!cipt->certinfo)
ret = CURLE_OUT_OF_MEMORY; ret = CURLE_OUT_OF_MEMORY;
else { else {
cipt->num_of_certs = cipf->num_of_certs; cipt->num_of_certs = cipf->num_of_certs;
for (i = 0; i < cipf->num_of_certs; i++) for(i = 0; i < cipf->num_of_certs; i++)
if(cipf->certinfo[i]) if(cipf->certinfo[i])
if(!(cipt->certinfo[i] = slist_convert(ccsid, if(!(cipt->certinfo[i] = slist_convert(ccsid,
cipf->certinfo[i], cipf->certinfo[i],
@@ -677,12 +680,18 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
*(struct curl_certinfo * *) paramp = cipt; *(struct curl_certinfo * *) paramp = cipt;
} }
}
else { break;
case CURLINFO_TLS_SESSION:
break;
default:
slp = (struct curl_slist * *) paramp; slp = (struct curl_slist * *) paramp;
if(*slp) if(*slp)
if(!(*slp = slist_convert(ccsid, *slp, ASCII_CCSID))) if(!(*slp = slist_convert(ccsid, *slp, ASCII_CCSID)))
ret = CURLE_OUT_OF_MEMORY; ret = CURLE_OUT_OF_MEMORY;
break;
} }
} }
@@ -715,7 +724,7 @@ static void
Curl_formadd_release_local(struct curl_forms * forms, int nargs, int skip) Curl_formadd_release_local(struct curl_forms * forms, int nargs, int skip)
{ {
while (nargs--) while(nargs--)
if(nargs != skip) if(nargs != skip)
if(Curl_is_formadd_string(forms[nargs].option)) if(Curl_is_formadd_string(forms[nargs].option))
if(forms[nargs].value) if(forms[nargs].value)
@@ -755,7 +764,7 @@ Curl_formadd_convert(struct curl_forms * forms,
return -1; return -1;
} }
cp2 = realloc(cp, l); /* Shorten buffer to the string size. */ cp2 = realloc(cp, l); /* Shorten buffer to the string size. */
if(cp2) if(cp2)
cp = cp2; cp = cp2;
@@ -763,7 +772,7 @@ Curl_formadd_convert(struct curl_forms * forms,
forms[formx].value = cp; forms[formx].value = cp;
if(lengthx >= 0) if(lengthx >= 0)
forms[lengthx].value = (char *) l; /* Update to length after conversion. */ forms[lengthx].value = (char *) l; /* Update length after conversion. */
return l; return l;
} }
@@ -826,7 +835,7 @@ curl_formadd_ccsid(struct curl_httppost * * httppost,
forms = (struct curl_forms *) NULL; forms = (struct curl_forms *) NULL;
va_start(arg, last_post); va_start(arg, last_post);
for (;;) { for(;;) {
/* Make sure there is still room for an item in local array. */ /* Make sure there is still room for an item in local array. */
if(nargs >= lformlen) { if(nargs >= lformlen) {
@@ -1111,11 +1120,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
if(testwarn) { if(testwarn) {
testwarn = 0; testwarn = 0;
#ifdef USE_TLS_SRP if((int) STRING_LAST != (int) STRING_BEARER + 1)
if((int) STRING_LAST != (int) STRING_TLSAUTH_PASSWORD + 1)
#else
if((int) STRING_LAST != (int) STRING_MAIL_AUTH + 1)
#endif
curl_mfprintf(stderr, curl_mfprintf(stderr,
"*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n"); "*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n");
} }
@@ -1143,6 +1148,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
case CURLOPT_ISSUERCERT: case CURLOPT_ISSUERCERT:
case CURLOPT_KEYPASSWD: case CURLOPT_KEYPASSWD:
case CURLOPT_KRBLEVEL: case CURLOPT_KRBLEVEL:
case CURLOPT_LOGIN_OPTIONS:
case CURLOPT_MAIL_FROM: case CURLOPT_MAIL_FROM:
case CURLOPT_MAIL_AUTH: case CURLOPT_MAIL_AUTH:
case CURLOPT_NETRC_FILE: case CURLOPT_NETRC_FILE:
@@ -1176,6 +1182,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
case CURLOPT_USERAGENT: case CURLOPT_USERAGENT:
case CURLOPT_USERNAME: case CURLOPT_USERNAME:
case CURLOPT_USERPWD: case CURLOPT_USERPWD:
case CURLOPT_XOAUTH2_BEARER:
s = va_arg(arg, char *); s = va_arg(arg, char *);
ccsid = va_arg(arg, unsigned int); ccsid = va_arg(arg, unsigned int);

View File

@@ -38,13 +38,13 @@ CURL_EXTERN char * curl_easy_unescape_ccsid(CURL * handle, const char * string,
int length, int * outlength, int length, int * outlength,
unsigned int sccsid, unsigned int sccsid,
unsigned int dccsid); unsigned int dccsid);
CURL_EXTERN struct curl_slist * curl_slist_append_ccsid(struct curl_slist * lst, CURL_EXTERN struct curl_slist * curl_slist_append_ccsid(struct curl_slist * l,
const char * data, const char * data,
unsigned int ccsid); unsigned int ccsid);
CURL_EXTERN time_t curl_getdate_ccsid(const char * p, const time_t * unused, CURL_EXTERN time_t curl_getdate_ccsid(const char * p, const time_t * unused,
unsigned int ccsid); unsigned int ccsid);
CURL_EXTERN curl_version_info_data * curl_version_info_ccsid(CURLversion stamp, CURL_EXTERN curl_version_info_data * curl_version_info_ccsid(CURLversion stamp,
unsigned int csid); unsigned int cid);
CURL_EXTERN const char * curl_easy_strerror_ccsid(CURLcode error, CURL_EXTERN const char * curl_easy_strerror_ccsid(CURLcode error,
unsigned int ccsid); unsigned int ccsid);
CURL_EXTERN const char * curl_share_strerror_ccsid(CURLSHcode error, CURL_EXTERN const char * curl_share_strerror_ccsid(CURLSHcode error,

View File

@@ -115,6 +115,8 @@
d c X'00004000' d c X'00004000'
d CURL_VERSION_NTLM_WB... d CURL_VERSION_NTLM_WB...
d c X'00008000' d c X'00008000'
d CURL_VERSION_HTTP2...
d c X'00010000'
* *
d HTTPPOST_FILENAME... d HTTPPOST_FILENAME...
d c X'00000001' d c X'00000001'
@@ -212,6 +214,8 @@
d c 1 d c 1
d CURL_HTTP_VERSION_1_1... d CURL_HTTP_VERSION_1_1...
d c 2 d c 2
d CURL_HTTP_VERSION_2_0...
d c 3
* *
d CURL_NETRC_IGNORED... d CURL_NETRC_IGNORED...
d c 0 d c 0
@@ -228,6 +232,12 @@
d c 2 d c 2
d CURL_SSLVERSION_SSLv3... d CURL_SSLVERSION_SSLv3...
d c 3 d c 3
d CURL_SSLVERSION_TLSv1_0...
d c 4
d CURL_SSLVERSION_TLSv1_1...
d c 5
d CURL_SSLVERSION_TLSv1_2...
d c 6
* *
d CURL_TLSAUTH_NONE... d CURL_TLSAUTH_NONE...
d c 0 d c 0
@@ -1162,6 +1172,16 @@
d c 00218 d c 00218
d CURLOPT_XFERINFOFUNCTION... d CURLOPT_XFERINFOFUNCTION...
d c 20219 d c 20219
d CURLOPT_XOAUTH2_BEARER...
d c 10220
d CURLOPT_DNS_INTERFACE...
d c 10221
d CURLOPT_DNS_LOCAL_IP4...
d c 10222
d CURLOPT_DNS_LOCAL_IP6...
d c 10223
d CURLOPT_LOGIN_OPTIONS...
d c 10224
* *
/if not defined(CURL_NO_OLDIES) /if not defined(CURL_NO_OLDIES)
d CURLOPT_SSLKEYPASSWD... d CURLOPT_SSLKEYPASSWD...
@@ -1329,10 +1349,35 @@
d c X'00100029' d c X'00100029'
d CURLINFO_LOCAL_PORT... CURLINFO_LONG + 42 d CURLINFO_LOCAL_PORT... CURLINFO_LONG + 42
d c X'0020002A' d c X'0020002A'
d CURLINFO_TLS_SESSION... CURLINFO_SLIST + 43
d c X'0040002B'
* *
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
d c X'00200002' d c X'00200002'
* *
d curl_sslbackend...
d s 10i 0 based(######ptr######) Enum
d CURLSSLBACKEND_NONE...
d c 0
d CURLSSLBACKEND_OPENSSL...
d c 1
d CURLSSLBACKEND_GNUTLS...
d c 2
d CURLSSLBACKEND_NSS...
d c 3
d CURLSSLBACKEND_QSOSSL...
d c 4
d CURLSSLBACKEND_GSKIT...
d c 5
d CURLSSLBACKEND_POLARSSL...
d c 6
d CURLSSLBACKEND_CYASSL...
d c 7
d CURLSSLBACKEND_SCHANNEL...
d c 8
d CURLSSLBACKEND_DARWINSSL...
d c 9
*
d curl_closepolicy... d curl_closepolicy...
d s 10i 0 based(######ptr######) Enum d s 10i 0 based(######ptr######) Enum
d CURLCLOSEPOLICY_OLDEST... d CURLCLOSEPOLICY_OLDEST...
@@ -1451,7 +1496,9 @@
d c 5 d c 5
d CURLM_UNKNOWN_OPTION... d CURLM_UNKNOWN_OPTION...
d c 6 d c 6
d CURLM_LAST c 7 d CURLM_ADDED_ALREADY...
d c 7
d CURLM_LAST c 8
* *
d CURLMSG s 10i 0 based(######ptr######) Enum d CURLMSG s 10i 0 based(######ptr######) Enum
d CURLMSG_NONE c 0 d CURLMSG_NONE c 0
@@ -1560,12 +1607,7 @@
d addrlen 10u 0 d addrlen 10u 0
d addr 16 struct sockaddr d addr 16 struct sockaddr
* *
d curl_khkey ds based(######ptr######) d curl_khtype s 10i 0 based(######ptr######) enum
d qualified
d key * const char *
d len 10u 0
d keytype 10i 0
*
d CURLKHTYPE_UNKNOWN... d CURLKHTYPE_UNKNOWN...
d c 0 d c 0
d CURLKHTYPE_RSA1... d CURLKHTYPE_RSA1...
@@ -1575,6 +1617,12 @@
d CURLKHTYPE_DSS... d CURLKHTYPE_DSS...
d c 3 d c 3
* *
d curl_khkey ds based(######ptr######)
d qualified
d key * const char *
d len 10u 0
d keytype like(curl_khtype)
*
d curl_forms ds based(######ptr######) d curl_forms ds based(######ptr######)
d qualified d qualified
d option like(CURLformoption) d option like(CURLformoption)
@@ -1622,6 +1670,12 @@
d group * char * d group * char *
d target * char * d target * char *
* *
d curl_tlssessioninfo...
d ds based(######ptr######)
d qualified
d backend like(curl_sslbackend)
d internals * void *
*
d curl_fileinfo ds based(######ptr######) d curl_fileinfo ds based(######ptr######)
d qualified d qualified
d filename * char * d filename * char *

View File

@@ -1,6 +1,16 @@
#!/bin/sh #!/bin/sh
setenv()
{
# Define and export.
eval ${1}="${2}"
export ${1}
}
case "${SCRIPTDIR}" in case "${SCRIPTDIR}" in
/*) ;; /*) ;;
*) SCRIPTDIR="`pwd`/${SCRIPTDIR}" *) SCRIPTDIR="`pwd`/${SCRIPTDIR}"
@@ -32,18 +42,23 @@ export SONAME
# #
################################################################################ ################################################################################
TARGETLIB='CURL' # Target OS/400 program library setenv TARGETLIB 'CURL' # Target OS/400 program library.
STATBNDDIR='CURL_A' # Static binding directory. setenv STATBNDDIR 'CURL_A' # Static binding directory.
DYNBNDDIR='CURL' # Dynamic binding directory. setenv DYNBNDDIR 'CURL' # Dynamic binding directory.
SRVPGM="CURL.${SONAME}" # Service program. setenv SRVPGM "CURL.${SONAME}" # Service program.
TGTCCSID='500' # Target CCSID of objects setenv TGTCCSID '500' # Target CCSID of objects.
DEBUG='*ALL' # Debug level setenv DEBUG '*ALL' # Debug level.
OPTIMIZE='10' # Optimisation level setenv OPTIMIZE '10' # Optimisation level
OUTPUT='*NONE' # Compilation output option. setenv OUTPUT '*NONE' # Compilation output option.
TGTRLS='V5R3M0' # Target OS release setenv TGTRLS 'V5R3M0' # Target OS release.
setenv IFSDIR '/curl' # Installation IFS directory.
export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM TGTCCSID DEBUG OPTIMIZE OUTPUT # Define ZLIB availability and locations.
export TGTRLS
setenv WITH_ZLIB 0 # Define to 1 to enable.
setenv ZLIB_INCLUDE '/zlib/include' # ZLIB include IFS directory.
setenv ZLIB_LIB 'ZLIB' # ZLIB library.
setenv ZLIB_BNDDIR 'ZLIB_A' # ZLIB binding directory.
################################################################################ ################################################################################
@@ -133,14 +148,26 @@ make_module()
CMD="${CMD} LOCALETYPE(*LOCALE)" CMD="${CMD} LOCALETYPE(*LOCALE)"
CMD="${CMD} INCDIR('/qibm/proddata/qadrt/include'" CMD="${CMD} INCDIR('/qibm/proddata/qadrt/include'"
CMD="${CMD} '${TOPDIR}/include/curl' '${TOPDIR}/include'" CMD="${CMD} '${TOPDIR}/include/curl' '${TOPDIR}/include'"
CMD="${CMD} '${TOPDIR}/packages/OS400' ${INCLUDES})" CMD="${CMD} '${TOPDIR}/packages/OS400'"
if [ "${WITH_ZLIB}" != "0" ]
then CMD="${CMD} '${ZLIB_INCLUDE}'"
fi
CMD="${CMD} ${INCLUDES})"
CMD="${CMD} TGTCCSID(${TGTCCSID}) TGTRLS(${TGTRLS})" CMD="${CMD} TGTCCSID(${TGTCCSID}) TGTRLS(${TGTRLS})"
CMD="${CMD} OUTPUT(${OUTPUT})" CMD="${CMD} OUTPUT(${OUTPUT})"
CMD="${CMD} OPTIMIZE(${OPTIMIZE})" CMD="${CMD} OPTIMIZE(${OPTIMIZE})"
CMD="${CMD} DBGVIEW(${DEBUG})" CMD="${CMD} DBGVIEW(${DEBUG})"
if [ "${3}" ] DEFINES="${3}"
then CMD="${CMD} DEFINE(${3})"
if [ "${WITH_ZLIB}" != "0" ]
then DEFINES="${DEFINES} HAVE_LIBZ HAVE_ZLIB_H"
fi
if [ "${DEFINES}" ]
then CMD="${CMD} DEFINE(${DEFINES})"
fi fi
system "${CMD}" system "${CMD}"
@@ -154,11 +181,17 @@ make_module()
db2_name() db2_name()
{ {
basename "${1}" | if [ "${2}" = 'nomangle' ]
tr 'a-z-' 'A-Z_' | then basename "${1}" |
sed -e 's/\..*//' \ tr 'a-z-' 'A-Z_' |
-e 's/^CURL_*/C/' \ sed -e 's/\..*//' \
-e 's/^\(.\).*\(.........\)$/\1\2/' -e 's/^\(.\).*\(.........\)$/\1\2/'
else basename "${1}" |
tr 'a-z-' 'A-Z_' |
sed -e 's/\..*//' \
-e 's/^CURL_*/C/' \
-e 's/^\(.\).*\(.........\)$/\1\2/'
fi
} }

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# #
# Installation of the include files in the OS/400 library. # Installation of the header files in the OS/400 library.
# #
SCRIPTDIR=`dirname "${0}"` SCRIPTDIR=`dirname "${0}"`
@@ -8,16 +8,16 @@ SCRIPTDIR=`dirname "${0}"`
cd "${TOPDIR}/include" cd "${TOPDIR}/include"
# Produce the curlbuild.h include file if not yet in distribution (CVS). # Produce the curlbuild.h header file if not yet in distribution (CVS).
if action_needed curl/curlbuild.h if action_needed curl/curlbuild.h
then if action_needed curl/curlbuild.h curl/curlbuild.h.dist then if action_needed curl/curlbuild.h curl/curlbuild.h.dist
then cp -p curl/curlbuild.h.dist curl/curlbuild.h then cp -p curl/curlbuild.h.dist curl/curlbuild.h
fi fi
fi fi
# Create the OS/400 source program file for the include files. # Create the OS/400 source program file for the header files.
SRCPF="${LIBIFSNAME}/H.FILE" SRCPF="${LIBIFSNAME}/H.FILE"
@@ -28,16 +28,25 @@ then CMD="CRTSRCPF FILE(${TARGETLIB}/H) RCDLEN(112)"
fi fi
# Create the IFS directory for the header files.
IFSINCLUDE="${IFSDIR}/include/curl"
if action_needed "${IFSINCLUDE}"
then mkdir -p "${IFSINCLUDE}"
fi
# Enumeration values are used as va_arg tagfields, so they MUST be # Enumeration values are used as va_arg tagfields, so they MUST be
# integers. # integers.
copy_hfile() copy_hfile()
{ {
destfile="${1}" destfile="${1}"
srcfile="${2}" srcfile="${2}"
shift shift
shift shift
sed -e '1i\ sed -e '1i\
#pragma enum(int)\ #pragma enum(int)\
' "${@}" -e '$a\ ' "${@}" -e '$a\
@@ -48,23 +57,34 @@ copy_hfile()
# Copy the header files. # Copy the header files.
for HFILE in curl/*.h ${SCRIPTDIR}/ccsidcurl.h for HFILE in curl/*.h ${SCRIPTDIR}/ccsidcurl.h
do DEST="${SRCPF}/`db2_name \"${HFILE}\"`.MBR" do case "`basename \"${HFILE}\" .h`" in
stdcheaders|typecheck-gcc)
continue;;
esac
DEST="${SRCPF}/`db2_name \"${HFILE}\" nomangle`.MBR"
if action_needed "${DEST}" "${HFILE}" if action_needed "${DEST}" "${HFILE}"
then copy_hfile "${DEST}" "${HFILE}" then copy_hfile "${DEST}" "${HFILE}"
IFSDEST="${IFSINCLUDE}/`basename \"${HFILE}\"`"
rm -f "${IFSDEST}"
ln -s "${DEST}" "${IFSDEST}"
fi fi
done done
# Copy the ILE/RPG include file, setting-up version number. # Copy the ILE/RPG header file, setting-up version number.
versioned_copy "${SCRIPTDIR}/curl.inc.in" "${SRCPF}/CURL.INC.MBR" versioned_copy "${SCRIPTDIR}/curl.inc.in" "${SRCPF}/CURL.INC.MBR"
rm -f "${IFSINCLUDE}/curl.inc.rpgle"
ln -s "${SRCPF}/CURL.INC.MBR" "${IFSINCLUDE}/curl.inc.rpgle"
# Duplicate file H as CURL to support more include path forms. # Duplicate file H as CURL to support more include path forms.
if action_needed "${LIBIFSNAME}/CURL.FILE" if action_needed "${LIBIFSNAME}/CURL.FILE"
then : then :
else system "DLTF FILE(${TARGETLIB}/CURL)" else system "DLTF FILE(${TARGETLIB}/CURL)"
fi fi
CMD="CRTDUPOBJ OBJ(H) FROMLIB(${TARGETLIB}) OBJTYPE(*FILE) TOLIB(*FROMLIB)" CMD="CRTDUPOBJ OBJ(H) FROMLIB(${TARGETLIB}) OBJTYPE(*FILE) TOLIB(*FROMLIB)"

View File

@@ -83,12 +83,12 @@ fi
# Gather the list of symbols to export. # Gather the list of symbols to export.
EXPORTS=`grep '^CURL_EXTERN[ ]' \ EXPORTS=`grep '^CURL_EXTERN[[:space:]]' \
"${TOPDIR}"/include/curl/*.h \ "${TOPDIR}"/include/curl/*.h \
"${SCRIPTDIR}/ccsidcurl.h" | "${SCRIPTDIR}/ccsidcurl.h" |
sed -e 's/^.*CURL_EXTERN[ ]\(.*\)(.*$/\1/' \ sed -e 's/^.*CURL_EXTERN[[:space:]]\(.*\)(.*$/\1/' \
-e 's/[ ]*$//' \ -e 's/[[:space:]]*$//' \
-e 's/^.*[ ][ ]*//' \ -e 's/^.*[[:space:]][[:space:]]*//' \
-e 's/^\*//' \ -e 's/^\*//' \
-e 's/(\(.*\))/\1/'` -e 's/(\(.*\))/\1/'`
@@ -121,7 +121,11 @@ if [ "${LINK}" ]
then CMD="CRTSRVPGM SRVPGM(${TARGETLIB}/${SRVPGM})" then CMD="CRTSRVPGM SRVPGM(${TARGETLIB}/${SRVPGM})"
CMD="${CMD} SRCFILE(${TARGETLIB}/TOOLS) SRCMBR(BNDSRC)" CMD="${CMD} SRCFILE(${TARGETLIB}/TOOLS) SRCMBR(BNDSRC)"
CMD="${CMD} MODULE(${TARGETLIB}/OS400)" CMD="${CMD} MODULE(${TARGETLIB}/OS400)"
CMD="${CMD} BNDDIR(${TARGETLIB}/${STATBNDDIR})" CMD="${CMD} BNDDIR(${TARGETLIB}/${STATBNDDIR}"
if [ "${WITH_ZLIB}" != 0 ]
then CMD="${CMD} ${ZLIB_LIB}/${ZLIB_BNDDIR}"
fi
CMD="${CMD})"
CMD="${CMD} BNDSRVPGM(QADRTTS QGLDCLNT QGLDBRDR)" CMD="${CMD} BNDSRVPGM(QADRTTS QGLDCLNT QGLDBRDR)"
CMD="${CMD} TEXT('curl API library')" CMD="${CMD} TEXT('curl API library')"
CMD="${CMD} TGTRLS(${TGTRLS})" CMD="${CMD} TGTRLS(${TGTRLS})"

View File

@@ -28,11 +28,11 @@ eval "`sed -e ': begin' \
-e 's/\\\\\\n/ /' \ -e 's/\\\\\\n/ /' \
-e 'b begin' \ -e 'b begin' \
-e '}' \ -e '}' \
-e '/^[A-Za-z_][A-Za-z0-9_]*[ ]*[=]/b keep' \ -e '/^[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[=]/b keep' \
-e 'd' \ -e 'd' \
-e ': keep' \ -e ': keep' \
-e 's/[ ]*=[ ]*/=/' \ -e 's/[[:space:]]*=[[:space:]]*/=/' \
-e 's/=\\(.*[^ ]\\)[ ]*$/=\\"\\1\\"/' \ -e 's/=\\(.*[^[:space:]]\\)[[:space:]]*$/=\\"\\1\\"/' \
-e 's/\\$(\\([^)]*\\))/${\\1}/g' \ -e 's/\\$(\\([^)]*\\))/${\\1}/g' \
< Makefile.inc`" < Makefile.inc`"

View File

@@ -38,6 +38,10 @@
#include <qadrt.h> #include <qadrt.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef USE_QSOSSL #ifdef USE_QSOSSL
#include <qsossl.h> #include <qsossl.h>
#endif #endif
@@ -97,11 +101,11 @@ thdbufdestroy(void * private)
localkey_t i; localkey_t i;
buffer_t * p; buffer_t * p;
if (private) { if(private) {
p = (buffer_t *) private; p = (buffer_t *) private;
for (i = (localkey_t) 0; i < LK_LAST; i++) { for(i = (localkey_t) 0; i < LK_LAST; i++) {
if (p->buf) if(p->buf)
free(p->buf); free(p->buf);
p++; p++;
@@ -116,13 +120,13 @@ static void
terminate(void) terminate(void)
{ {
if (Curl_thread_buffer == buffer_threaded) { if(Curl_thread_buffer == buffer_threaded) {
locbufs = pthread_getspecific(thdkey); locbufs = pthread_getspecific(thdkey);
pthread_setspecific(thdkey, (void *) NULL); pthread_setspecific(thdkey, (void *) NULL);
pthread_key_delete(thdkey); pthread_key_delete(thdkey);
} }
if (Curl_thread_buffer != buffer_undef) { if(Curl_thread_buffer != buffer_undef) {
thdbufdestroy((void *) locbufs); thdbufdestroy((void *) locbufs);
locbufs = (buffer_t *) NULL; locbufs = (buffer_t *) NULL;
} }
@@ -140,31 +144,31 @@ get_buffer(buffer_t * buf, long size)
/* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long. /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long.
Return the buffer address. */ Return the buffer address. */
if (size < 0) if(size < 0)
return buf->buf; return buf->buf;
if (!buf->buf) { if(!buf->buf) {
if ((buf->buf = malloc(size))) if((buf->buf = malloc(size)))
buf->size = size; buf->size = size;
return buf->buf; return buf->buf;
} }
if ((unsigned long) size <= buf->size) { if((unsigned long) size <= buf->size) {
/* Shorten the buffer only if it frees a significant byte count. This /* Shorten the buffer only if it frees a significant byte count. This
avoids some realloc() overhead. */ avoids some realloc() overhead. */
if (buf->size - size < MIN_BYTE_GAIN) if(buf->size - size < MIN_BYTE_GAIN)
return buf->buf; return buf->buf;
} }
/* Resize the buffer. */ /* Resize the buffer. */
if ((cp = realloc(buf->buf, size))) { if((cp = realloc(buf->buf, size))) {
buf->buf = cp; buf->buf = cp;
buf->size = size; buf->size = size;
} }
else if (size <= buf->size) else if(size <= buf->size)
cp = buf->buf; cp = buf->buf;
return cp; return cp;
@@ -191,16 +195,16 @@ buffer_threaded(localkey_t key, long size)
bufs = (buffer_t *) pthread_getspecific(thdkey); bufs = (buffer_t *) pthread_getspecific(thdkey);
if (!bufs) { if(!bufs) {
if (size < 0) if(size < 0)
return (char *) NULL; /* No buffer yet. */ return (char *) NULL; /* No buffer yet. */
/* Allocate buffer descriptors for the current thread. */ /* Allocate buffer descriptors for the current thread. */
if (!(bufs = calloc((size_t) LK_LAST, sizeof *bufs))) if(!(bufs = calloc((size_t) LK_LAST, sizeof *bufs)))
return (char *) NULL; return (char *) NULL;
if (pthread_setspecific(thdkey, (void *) bufs)) { if(pthread_setspecific(thdkey, (void *) bufs)) {
free(bufs); free(bufs);
return (char *) NULL; return (char *) NULL;
} }
@@ -222,11 +226,10 @@ buffer_undef(localkey_t key, long size)
/* Determine if we can use pthread-specific data. */ /* Determine if we can use pthread-specific data. */
if (Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */ if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */
if (!pthread_key_create(&thdkey, thdbufdestroy)) if(!pthread_key_create(&thdkey, thdbufdestroy))
Curl_thread_buffer = buffer_threaded; Curl_thread_buffer = buffer_threaded;
else if (!(locbufs = calloc((size_t) LK_LAST, else if(!(locbufs = calloc((size_t) LK_LAST, sizeof *locbufs))) {
sizeof *locbufs))) {
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
return (char *) NULL; return (char *) NULL;
} }
@@ -241,6 +244,28 @@ buffer_undef(localkey_t key, long size)
} }
static char *
set_thread_string(localkey_t key, const char * s)
{
int i;
char * cp;
if(!s)
return (char *) NULL;
i = strlen(s) + 1;
cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1);
if(cp) {
i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i);
cp[i] = '\0';
}
return cp;
}
int int
Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen, Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
char * nodename, curl_socklen_t nodenamelen, char * nodename, curl_socklen_t nodenamelen,
@@ -256,13 +281,13 @@ Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
enodename = (char *) NULL; enodename = (char *) NULL;
eservname = (char *) NULL; eservname = (char *) NULL;
if (nodename && nodenamelen) if(nodename && nodenamelen)
if (!(enodename = malloc(nodenamelen))) if(!(enodename = malloc(nodenamelen)))
return EAI_MEMORY; return EAI_MEMORY;
if (servname && servnamelen) if(servname && servnamelen)
if (!(eservname = malloc(servnamelen))) { if(!(eservname = malloc(servnamelen))) {
if (enodename) if(enodename)
free(enodename); free(enodename);
return EAI_MEMORY; return EAI_MEMORY;
@@ -271,24 +296,24 @@ Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
status = getnameinfo(sa, salen, enodename, nodenamelen, status = getnameinfo(sa, salen, enodename, nodenamelen,
eservname, servnamelen, flags); eservname, servnamelen, flags);
if (!status) { if(!status) {
if (enodename) { if(enodename) {
i = QadrtConvertE2A(nodename, enodename, i = QadrtConvertE2A(nodename, enodename,
nodenamelen - 1, strlen(enodename)); nodenamelen - 1, strlen(enodename));
nodename[i] = '\0'; nodename[i] = '\0';
} }
if (eservname) { if(eservname) {
i = QadrtConvertE2A(servname, eservname, i = QadrtConvertE2A(servname, eservname,
servnamelen - 1, strlen(eservname)); servnamelen - 1, strlen(eservname));
servname[i] = '\0'; servname[i] = '\0';
} }
} }
if (enodename) if(enodename)
free(enodename); free(enodename);
if (eservname) if(eservname)
free(eservname); free(eservname);
return status; return status;
@@ -309,21 +334,21 @@ Curl_getaddrinfo_a(const char * nodename, const char * servname,
enodename = (char *) NULL; enodename = (char *) NULL;
eservname = (char *) NULL; eservname = (char *) NULL;
if (nodename) { if(nodename) {
i = strlen(nodename); i = strlen(nodename);
if (!(enodename = malloc(i + 1))) if(!(enodename = malloc(i + 1)))
return EAI_MEMORY; return EAI_MEMORY;
i = QadrtConvertA2E(enodename, nodename, i, i); i = QadrtConvertA2E(enodename, nodename, i, i);
enodename[i] = '\0'; enodename[i] = '\0';
} }
if (servname) { if(servname) {
i = strlen(servname); i = strlen(servname);
if (!(eservname = malloc(i + 1))) { if(!(eservname = malloc(i + 1))) {
if (enodename) if(enodename)
free(enodename); free(enodename);
return EAI_MEMORY; return EAI_MEMORY;
@@ -335,10 +360,10 @@ Curl_getaddrinfo_a(const char * nodename, const char * servname,
status = getaddrinfo(enodename, eservname, hints, res); status = getaddrinfo(enodename, eservname, hints, res);
if (enodename) if(enodename)
free(enodename); free(enodename);
if (eservname) if(eservname)
free(eservname); free(eservname);
return status; return status;
@@ -357,13 +382,13 @@ Curl_SSL_Init_Application_a(SSLInitApp * init_app)
unsigned int i; unsigned int i;
SSLInitApp ia; SSLInitApp ia;
if (!init_app || !init_app->applicationID || !init_app->applicationIDLen) if(!init_app || !init_app->applicationID || !init_app->applicationIDLen)
return SSL_Init_Application(init_app); return SSL_Init_Application(init_app);
memcpy((char *) &ia, (char *) init_app, sizeof ia); memcpy((char *) &ia, (char *) init_app, sizeof ia);
i = ia.applicationIDLen; i = ia.applicationIDLen;
if (!(ia.applicationID = malloc(i + 1))) { if(!(ia.applicationID = malloc(i + 1))) {
errno = ENOMEM; errno = ENOMEM;
return SSL_ERROR_IO; return SSL_ERROR_IO;
} }
@@ -386,15 +411,15 @@ Curl_SSL_Init_a(SSLInit * init)
unsigned int i; unsigned int i;
SSLInit ia; SSLInit ia;
if (!init || (!init->keyringFileName && !init->keyringPassword)) if(!init || (!init->keyringFileName && !init->keyringPassword))
return SSL_Init(init); return SSL_Init(init);
memcpy((char *) &ia, (char *) init, sizeof ia); memcpy((char *) &ia, (char *) init, sizeof ia);
if (ia.keyringFileName) { if(ia.keyringFileName) {
i = strlen(ia.keyringFileName); i = strlen(ia.keyringFileName);
if (!(ia.keyringFileName = malloc(i + 1))) { if(!(ia.keyringFileName = malloc(i + 1))) {
errno = ENOMEM; errno = ENOMEM;
return SSL_ERROR_IO; return SSL_ERROR_IO;
} }
@@ -403,11 +428,11 @@ Curl_SSL_Init_a(SSLInit * init)
ia.keyringFileName[i] = '\0'; ia.keyringFileName[i] = '\0';
} }
if (ia.keyringPassword) { if(ia.keyringPassword) {
i = strlen(ia.keyringPassword); i = strlen(ia.keyringPassword);
if (!(ia.keyringPassword = malloc(i + 1))) { if(!(ia.keyringPassword = malloc(i + 1))) {
if (ia.keyringFileName) if(ia.keyringFileName)
free(ia.keyringFileName); free(ia.keyringFileName);
errno = ENOMEM; errno = ENOMEM;
@@ -420,10 +445,10 @@ Curl_SSL_Init_a(SSLInit * init)
rc = SSL_Init(&ia); rc = SSL_Init(&ia);
if (ia.keyringFileName) if(ia.keyringFileName)
free(ia.keyringFileName); free(ia.keyringFileName);
if (ia.keyringPassword) if(ia.keyringPassword)
free(ia.keyringPassword); free(ia.keyringPassword);
return rc; return rc;
@@ -434,23 +459,8 @@ char *
Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp) Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp)
{ {
int i; return set_thread_string(LK_SSL_ERROR,
char * cp; SSL_Strerror(sslreturnvalue, serrmsgp));
char * cp2;
cp = SSL_Strerror(sslreturnvalue, serrmsgp);
if (!cp)
return cp;
i = strlen(cp);
if (!(cp2 = Curl_thread_buffer(LK_SSL_ERROR, MAX_CONV_EXPANSION * i + 1)))
return cp2;
i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
cp2[i] = '\0';
return cp2;
} }
#endif /* USE_QSOSSL */ #endif /* USE_QSOSSL */
@@ -534,7 +544,7 @@ gsk_free_handle(struct Curl_gsk_descriptor * p)
{ {
struct gskstrlist * q; struct gskstrlist * q;
while ((q = p->strlist)) { while((q = p->strlist)) {
p->strlist = q; p->strlist = q;
free((void *) q->asciistr); free((void *) q->asciistr);
free(q); free(q);
@@ -555,7 +565,7 @@ Curl_gsk_environment_close(gsk_handle * my_env_handle)
if(!*my_env_handle) if(!*my_env_handle)
return GSK_INVALID_HANDLE; return GSK_INVALID_HANDLE;
p = (struct Curl_gsk_descriptor *) *my_env_handle; p = (struct Curl_gsk_descriptor *) *my_env_handle;
if ((rc = gsk_environment_close(&p->h)) == GSK_OK) { if((rc = gsk_environment_close(&p->h)) == GSK_OK) {
gsk_free_handle(p); gsk_free_handle(p);
*my_env_handle = (gsk_handle) NULL; *my_env_handle = (gsk_handle) NULL;
} }
@@ -575,7 +585,7 @@ Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
if(!*my_session_handle) if(!*my_session_handle)
return GSK_INVALID_HANDLE; return GSK_INVALID_HANDLE;
p = (struct Curl_gsk_descriptor *) *my_session_handle; p = (struct Curl_gsk_descriptor *) *my_session_handle;
if ((rc = gsk_secure_soc_close(&p->h)) == GSK_OK) { if((rc = gsk_secure_soc_close(&p->h)) == GSK_OK) {
gsk_free_handle(p); gsk_free_handle(p);
*my_session_handle = (gsk_handle) NULL; *my_session_handle = (gsk_handle) NULL;
} }
@@ -627,7 +637,7 @@ Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
p = (struct Curl_gsk_descriptor *) my_gsk_handle; p = (struct Curl_gsk_descriptor *) my_gsk_handle;
if(!bufSize) if(!bufSize)
bufSize = strlen(buffer); bufSize = strlen(buffer);
if (!(ebcdicbuf = malloc(bufSize + 1))) if(!(ebcdicbuf = malloc(bufSize + 1)))
return GSK_INSUFFICIENT_STORAGE; return GSK_INSUFFICIENT_STORAGE;
QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize); QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
ebcdicbuf[bufSize] = '\0'; ebcdicbuf[bufSize] = '\0';
@@ -689,7 +699,7 @@ cachestring(struct Curl_gsk_descriptor * p,
char * asciibuf; char * asciibuf;
struct gskstrlist * sp; struct gskstrlist * sp;
for (sp = p->strlist; sp; sp = sp->next) for(sp = p->strlist; sp; sp = sp->next)
if(sp->ebcdicstr == ebcdicbuf) if(sp->ebcdicstr == ebcdicbuf)
break; break;
if(!sp) { if(!sp) {
@@ -726,7 +736,7 @@ Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
if(!buffer || !bufSize) if(!buffer || !bufSize)
return GSK_OS400_ERROR_INVALID_POINTER; return GSK_OS400_ERROR_INVALID_POINTER;
p = (struct Curl_gsk_descriptor *) my_gsk_handle; p = (struct Curl_gsk_descriptor *) my_gsk_handle;
if ((rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen)) != GSK_OK) if((rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen)) != GSK_OK)
return rc; return rc;
if((rc = cachestring(p, mybuf, mylen, buffer)) == GSK_OK) if((rc = cachestring(p, mybuf, mylen, buffer)) == GSK_OK)
*bufSize = mylen; *bufSize = mylen;
@@ -825,23 +835,7 @@ const char *
Curl_gsk_strerror_a(int gsk_return_value) Curl_gsk_strerror_a(int gsk_return_value)
{ {
int i; return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
const char * cp;
char * cp2;
cp = gsk_strerror(gsk_return_value);
if (!cp)
return cp;
i = strlen(cp);
if (!(cp2 = Curl_thread_buffer(LK_GSK_ERROR, MAX_CONV_EXPANSION * i + 1)))
return cp2;
i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
cp2[i] = '\0';
return cp2;
} }
int int
@@ -878,11 +872,11 @@ Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf)
i = buf->length; i = buf->length;
if (i) { if(i) {
if (!(t = malloc(i))) { if(!(t = malloc(i))) {
gss_release_buffer(minor_status, buf); gss_release_buffer(minor_status, buf);
if (minor_status) if(minor_status)
*minor_status = ENOMEM; *minor_status = ENOMEM;
return -1; return -1;
@@ -906,14 +900,14 @@ Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
unsigned int i; unsigned int i;
gss_buffer_desc in; gss_buffer_desc in;
if (!in_name || !in_name->value || !in_name->length) if(!in_name || !in_name->value || !in_name->length)
return gss_import_name(minor_status, in_name, in_name_type, out_name); return gss_import_name(minor_status, in_name, in_name_type, out_name);
memcpy((char *) &in, (char *) in_name, sizeof in); memcpy((char *) &in, (char *) in_name, sizeof in);
i = in.length; i = in.length;
if (!(in.value = malloc(i + 1))) { if(!(in.value = malloc(i + 1))) {
if (minor_status) if(minor_status)
*minor_status = ENOMEM; *minor_status = ENOMEM;
return GSS_S_FAILURE; return GSS_S_FAILURE;
@@ -938,15 +932,15 @@ Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
rc = gss_display_status(minor_status, status_value, status_type, rc = gss_display_status(minor_status, status_value, status_type,
mech_type, message_context, status_string); mech_type, message_context, status_string);
if (rc != GSS_S_COMPLETE || !status_string || if(rc != GSS_S_COMPLETE || !status_string ||
!status_string->length || !status_string->value) !status_string->length || !status_string->value)
return rc; return rc;
/* No way to allocate a buffer here, because it will be released by /* No way to allocate a buffer here, because it will be released by
gss_release_buffer(). The solution is to overwrite the EBCDIC buffer gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
with ASCII to return it. */ with ASCII to return it. */
if (Curl_gss_convert_in_place(minor_status, status_string)) if(Curl_gss_convert_in_place(minor_status, status_string))
return GSS_S_FAILURE; return GSS_S_FAILURE;
return rc; return rc;
@@ -954,7 +948,8 @@ Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
OM_uint32 OM_uint32
Curl_gss_init_sec_context_a(OM_uint32 * minor_status, gss_cred_id_t cred_handle, Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
gss_cred_id_t cred_handle,
gss_ctx_id_t * context_handle, gss_ctx_id_t * context_handle,
gss_name_t target_name, gss_OID mech_type, gss_name_t target_name, gss_OID mech_type,
gss_flags_t req_flags, OM_uint32 time_req, gss_flags_t req_flags, OM_uint32 time_req,
@@ -972,12 +967,12 @@ Curl_gss_init_sec_context_a(OM_uint32 * minor_status, gss_cred_id_t cred_handle,
in.value = NULL; in.value = NULL;
if ((inp = input_token)) if((inp = input_token))
if (inp->length && inp->value) { if(inp->length && inp->value) {
i = inp->length; i = inp->length;
if (!(in.value = malloc(i + 1))) { if(!(in.value = malloc(i + 1))) {
if (minor_status) if(minor_status)
*minor_status = ENOMEM; *minor_status = ENOMEM;
return GSS_S_FAILURE; return GSS_S_FAILURE;
@@ -994,10 +989,10 @@ Curl_gss_init_sec_context_a(OM_uint32 * minor_status, gss_cred_id_t cred_handle,
input_chan_bindings, inp, actual_mech_type, input_chan_bindings, inp, actual_mech_type,
output_token, ret_flags, time_rec); output_token, ret_flags, time_rec);
if (in.value) if(in.value)
free(in.value); free(in.value);
if (rc != GSS_S_COMPLETE || !output_token || if(rc != GSS_S_COMPLETE || !output_token ||
!output_token->length || !output_token->value) !output_token->length || !output_token->value)
return rc; return rc;
@@ -1005,7 +1000,7 @@ Curl_gss_init_sec_context_a(OM_uint32 * minor_status, gss_cred_id_t cred_handle,
gss_release_buffer(). The solution is to overwrite the EBCDIC buffer gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
with ASCII to return it. */ with ASCII to return it. */
if (Curl_gss_convert_in_place(minor_status, output_token)) if(Curl_gss_convert_in_place(minor_status, output_token))
return GSS_S_FAILURE; return GSS_S_FAILURE;
return rc; return rc;
@@ -1022,7 +1017,7 @@ Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
rc = gss_delete_sec_context(minor_status, context_handle, output_token); rc = gss_delete_sec_context(minor_status, context_handle, output_token);
if (rc != GSS_S_COMPLETE || !output_token || if(rc != GSS_S_COMPLETE || !output_token ||
!output_token->length || !output_token->value) !output_token->length || !output_token->value)
return rc; return rc;
@@ -1030,7 +1025,7 @@ Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
gss_release_buffer(). The solution is to overwrite the EBCDIC buffer gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
with ASCII to return it. */ with ASCII to return it. */
if (Curl_gss_convert_in_place(minor_status, output_token)) if(Curl_gss_convert_in_place(minor_status, output_token))
return GSS_S_FAILURE; return GSS_S_FAILURE;
return rc; return rc;
@@ -1051,12 +1046,12 @@ Curl_ldap_init_a(char * host, int port)
char * ehost; char * ehost;
void * result; void * result;
if (!host) if(!host)
return (void *) ldap_init(host, port); return (void *) ldap_init(host, port);
i = strlen(host); i = strlen(host);
if (!(ehost = malloc(i + 1))) if(!(ehost = malloc(i + 1)))
return (void *) NULL; return (void *) NULL;
QadrtConvertA2E(ehost, host, i, i); QadrtConvertA2E(ehost, host, i, i);
@@ -1078,21 +1073,21 @@ Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd)
edn = (char *) NULL; edn = (char *) NULL;
epasswd = (char *) NULL; epasswd = (char *) NULL;
if (dn) { if(dn) {
i = strlen(dn); i = strlen(dn);
if (!(edn = malloc(i + 1))) if(!(edn = malloc(i + 1)))
return LDAP_NO_MEMORY; return LDAP_NO_MEMORY;
QadrtConvertA2E(edn, dn, i, i); QadrtConvertA2E(edn, dn, i, i);
edn[i] = '\0'; edn[i] = '\0';
} }
if (passwd) { if(passwd) {
i = strlen(passwd); i = strlen(passwd);
if (!(epasswd = malloc(i + 1))) { if(!(epasswd = malloc(i + 1))) {
if (edn) if(edn)
free(edn); free(edn);
return LDAP_NO_MEMORY; return LDAP_NO_MEMORY;
@@ -1104,10 +1099,10 @@ Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd)
i = ldap_simple_bind_s(ld, edn, epasswd); i = ldap_simple_bind_s(ld, edn, epasswd);
if (epasswd) if(epasswd)
free(epasswd); free(epasswd);
if (edn) if(edn)
free(edn); free(edn);
return i; return i;
@@ -1131,10 +1126,10 @@ Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
eattrs = (char * *) NULL; eattrs = (char * *) NULL;
status = LDAP_SUCCESS; status = LDAP_SUCCESS;
if (base) { if(base) {
i = strlen(base); i = strlen(base);
if (!(ebase = malloc(i + 1))) if(!(ebase = malloc(i + 1)))
status = LDAP_NO_MEMORY; status = LDAP_NO_MEMORY;
else { else {
QadrtConvertA2E(ebase, base, i, i); QadrtConvertA2E(ebase, base, i, i);
@@ -1142,10 +1137,10 @@ Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
} }
} }
if (filter && status == LDAP_SUCCESS) { if(filter && status == LDAP_SUCCESS) {
i = strlen(filter); i = strlen(filter);
if (!(efilter = malloc(i + 1))) if(!(efilter = malloc(i + 1)))
status = LDAP_NO_MEMORY; status = LDAP_NO_MEMORY;
else { else {
QadrtConvertA2E(efilter, filter, i, i); QadrtConvertA2E(efilter, filter, i, i);
@@ -1153,17 +1148,17 @@ Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
} }
} }
if (attrs && status == LDAP_SUCCESS) { if(attrs && status == LDAP_SUCCESS) {
for (i = 0; attrs[i++];) for(i = 0; attrs[i++];)
; ;
if (!(eattrs = calloc(i, sizeof *eattrs))) if(!(eattrs = calloc(i, sizeof *eattrs)))
status = LDAP_NO_MEMORY; status = LDAP_NO_MEMORY;
else { else {
for (j = 0; attrs[j]; j++) { for(j = 0; attrs[j]; j++) {
i = strlen(attrs[j]); i = strlen(attrs[j]);
if (!(eattrs[j] = malloc(i + 1))) { if(!(eattrs[j] = malloc(i + 1))) {
status = LDAP_NO_MEMORY; status = LDAP_NO_MEMORY;
break; break;
} }
@@ -1174,22 +1169,22 @@ Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
} }
} }
if (status == LDAP_SUCCESS) if(status == LDAP_SUCCESS)
status = ldap_search_s(ld, ebase? ebase: "", scope, status = ldap_search_s(ld, ebase? ebase: "", scope,
efilter? efilter: "(objectclass=*)", efilter? efilter: "(objectclass=*)",
eattrs, attrsonly, res); eattrs, attrsonly, res);
if (eattrs) { if(eattrs) {
for (j = 0; eattrs[j]; j++) for(j = 0; eattrs[j]; j++)
free(eattrs[j]); free(eattrs[j]);
free(eattrs); free(eattrs);
} }
if (efilter) if(efilter)
free(efilter); free(efilter);
if (ebase) if(ebase)
free(ebase); free(ebase);
return status; return status;
@@ -1206,10 +1201,10 @@ Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
cp = (char *) NULL; cp = (char *) NULL;
if (attr) { if(attr) {
i = strlen(attr); i = strlen(attr);
if (!(cp = malloc(i + 1))) { if(!(cp = malloc(i + 1))) {
ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL, ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
ldap_err2string(LDAP_NO_MEMORY)); ldap_err2string(LDAP_NO_MEMORY));
return (struct berval * *) NULL; return (struct berval * *) NULL;
@@ -1221,11 +1216,11 @@ Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
result = ldap_get_values_len(ld, entry, cp); result = ldap_get_values_len(ld, entry, cp);
if (cp) if(cp)
free(cp); free(cp);
/* Result data are binary in nature, so they haven't been converted to EBCDIC. /* Result data are binary in nature, so they haven't been
Therefore do not convert. */ converted to EBCDIC. Therefore do not convert. */
return result; return result;
} }
@@ -1235,23 +1230,7 @@ char *
Curl_ldap_err2string_a(int error) Curl_ldap_err2string_a(int error)
{ {
int i; return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
char * cp;
char * cp2;
cp = ldap_err2string(error);
if (!cp)
return cp;
i = strlen(cp);
if (!(cp2 = Curl_thread_buffer(LK_LDAP_ERROR, MAX_CONV_EXPANSION * i + 1)))
return cp2;
i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i);
cp2[i] = '\0';
return cp2;
} }
@@ -1265,12 +1244,12 @@ Curl_ldap_get_dn_a(void * ld, LDAPMessage * entry)
cp = ldap_get_dn(ld, entry); cp = ldap_get_dn(ld, entry);
if (!cp) if(!cp)
return cp; return cp;
i = strlen(cp); i = strlen(cp);
if (!(cp2 = malloc(i + 1))) if(!(cp2 = malloc(i + 1)))
return cp2; return cp2;
QadrtConvertE2A(cp2, cp, i, i); QadrtConvertE2A(cp2, cp, i, i);
@@ -1297,12 +1276,12 @@ Curl_ldap_first_attribute_a(void * ld,
cp = ldap_first_attribute(ld, entry, berptr); cp = ldap_first_attribute(ld, entry, berptr);
if (!cp) if(!cp)
return cp; return cp;
i = strlen(cp); i = strlen(cp);
if (!(cp2 = malloc(i + 1))) if(!(cp2 = malloc(i + 1)))
return cp2; return cp2;
QadrtConvertE2A(cp2, cp, i, i); QadrtConvertE2A(cp2, cp, i, i);
@@ -1329,12 +1308,12 @@ Curl_ldap_next_attribute_a(void * ld,
cp = ldap_next_attribute(ld, entry, berptr); cp = ldap_next_attribute(ld, entry, berptr);
if (!cp) if(!cp)
return cp; return cp;
i = strlen(cp); i = strlen(cp);
if (!(cp2 = malloc(i + 1))) if(!(cp2 = malloc(i + 1)))
return cp2; return cp2;
QadrtConvertE2A(cp2, cp, i, i); QadrtConvertE2A(cp2, cp, i, i);
@@ -1364,8 +1343,8 @@ convert_sockaddr(struct sockaddr_storage * dstaddr,
/* Convert a socket address into job CCSID, if needed. */ /* Convert a socket address into job CCSID, if needed. */
if (!srcaddr || srclen < offsetof(struct sockaddr, sa_family) + if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) { sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -1398,7 +1377,7 @@ Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)
i = convert_sockaddr(&laddr, destaddr, addrlen); i = convert_sockaddr(&laddr, destaddr, addrlen);
if (i < 0) if(i < 0)
return -1; return -1;
return connect(sd, (struct sockaddr *) &laddr, i); return connect(sd, (struct sockaddr *) &laddr, i);
@@ -1414,7 +1393,7 @@ Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)
i = convert_sockaddr(&laddr, localaddr, addrlen); i = convert_sockaddr(&laddr, localaddr, addrlen);
if (i < 0) if(i < 0)
return -1; return -1;
return bind(sd, (struct sockaddr *) &laddr, i); return bind(sd, (struct sockaddr *) &laddr, i);
@@ -1431,7 +1410,7 @@ Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
i = convert_sockaddr(&laddr, dstaddr, addrlen); i = convert_sockaddr(&laddr, dstaddr, addrlen);
if (i < 0) if(i < 0)
return -1; return -1;
return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i); return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
@@ -1450,7 +1429,7 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
struct sockaddr_un * dstu; struct sockaddr_un * dstu;
struct sockaddr_storage laddr; struct sockaddr_storage laddr;
if (!fromaddr || !addrlen || *addrlen <= 0) if(!fromaddr || !addrlen || *addrlen <= 0)
return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen); return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
laddrlen = sizeof laddr; laddrlen = sizeof laddr;
@@ -1458,7 +1437,7 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
rcvlen = recvfrom(sd, buffer, buflen, flags, rcvlen = recvfrom(sd, buffer, buflen, flags,
(struct sockaddr *) &laddr, &laddrlen); (struct sockaddr *) &laddr, &laddrlen);
if (rcvlen < 0) if(rcvlen < 0)
return rcvlen; return rcvlen;
switch (laddr.ss_family) { switch (laddr.ss_family) {
@@ -1471,7 +1450,7 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
i = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, i, laddrlen); i = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, i, laddrlen);
laddrlen = i + offsetof(struct sockaddr_un, sun_path); laddrlen = i + offsetof(struct sockaddr_un, sun_path);
if (laddrlen < *addrlen) if(laddrlen < *addrlen)
dstu->sun_path[i] = '\0'; dstu->sun_path[i] = '\0';
break; break;
@@ -1480,10 +1459,10 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
break; break;
default: default:
if (laddrlen > *addrlen) if(laddrlen > *addrlen)
laddrlen = *addrlen; laddrlen = *addrlen;
if (laddrlen) if(laddrlen)
memcpy((char *) fromaddr, (char *) &laddr, laddrlen); memcpy((char *) fromaddr, (char *) &laddr, laddrlen);
break; break;
@@ -1492,3 +1471,79 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
*addrlen = laddrlen; *addrlen = laddrlen;
return rcvlen; return rcvlen;
} }
#ifdef HAVE_LIBZ
const char *
Curl_os400_zlibVersion(void)
{
return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
}
int
Curl_os400_inflateInit_(z_streamp strm, const char * version, int stream_size)
{
z_const char * msgb4 = strm->msg;
int ret;
ret = inflateInit(strm);
if(strm->msg != msgb4)
strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
return ret;
}
int
Curl_os400_inflateInit2_(z_streamp strm, int windowBits,
const char * version, int stream_size)
{
z_const char * msgb4 = strm->msg;
int ret;
ret = inflateInit2(strm, windowBits);
if(strm->msg != msgb4)
strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
return ret;
}
int
Curl_os400_inflate(z_streamp strm, int flush)
{
z_const char * msgb4 = strm->msg;
int ret;
ret = inflate(strm, flush);
if(strm->msg != msgb4)
strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
return ret;
}
int
Curl_os400_inflateEnd(z_streamp strm)
{
z_const char * msgb4 = strm->msg;
int ret;
ret = inflateEnd(strm);
if(strm->msg != msgb4)
strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
return ret;
}
#endif

View File

@@ -39,6 +39,8 @@ typedef enum {
LK_EASY_STRERROR, LK_EASY_STRERROR,
LK_SHARE_STRERROR, LK_SHARE_STRERROR,
LK_MULTI_STRERROR, LK_MULTI_STRERROR,
LK_ZLIB_VERSION,
LK_ZLIB_MSG,
LK_LAST LK_LAST
} localkey_t; } localkey_t;

View File

@@ -32,14 +32,14 @@
#include "memdebug.h" /* keep this as LAST include */ #include "memdebug.h" /* keep this as LAST include */
/* /*
** callback for CURLOPT_PROGRESSFUNCTION ** callback for CURLOPT_XFERINFOFUNCTION
*/ */
#define MAX_BARLENGTH 256 #define MAX_BARLENGTH 256
int tool_progress_cb(void *clientp, int tool_progress_cb(void *clientp,
double dltotal, double dlnow, curl_off_t dltotal, curl_off_t dlnow,
double ultotal, double ulnow) curl_off_t ultotal, curl_off_t ulnow)
{ {
/* The original progress-bar source code was written for curl by Lars Aas, /* The original progress-bar source code was written for curl by Lars Aas,
and this new edition inherits some of his concepts. */ and this new edition inherits some of his concepts. */
@@ -60,10 +60,10 @@ int tool_progress_cb(void *clientp,
return 0; return 0;
/* expected transfer size */ /* expected transfer size */
total = (curl_off_t)dltotal + (curl_off_t)ultotal + bar->initial_size; total = dltotal + ultotal + bar->initial_size;
/* we've come this far */ /* we've come this far */
point = (curl_off_t)dlnow + (curl_off_t)ulnow + bar->initial_size; point = dlnow + ulnow + bar->initial_size;
if(point > total) if(point > total)
/* we have got more than the expected total! */ /* we have got more than the expected total! */

View File

@@ -43,8 +43,8 @@ void progressbarinit(struct ProgressData *bar,
*/ */
int tool_progress_cb(void *clientp, int tool_progress_cb(void *clientp,
double dltotal, double dlnow, curl_off_t dltotal, curl_off_t dlnow,
double ultotal, double ulnow); curl_off_t ultotal, curl_off_t ulnow);
#endif /* HEADER_CURL_TOOL_CB_PRG_H */ #endif /* HEADER_CURL_TOOL_CB_PRG_H */

View File

@@ -74,6 +74,7 @@ struct Configurable {
0 => -s is used to NOT show errors 0 => -s is used to NOT show errors
1 => -S has been used to show errors */ 1 => -S has been used to show errors */
char *userpwd; char *userpwd;
char *login_options;
char *tls_username; char *tls_username;
char *tls_password; char *tls_password;
char *tls_authtype; char *tls_authtype;

View File

@@ -184,6 +184,9 @@ static const struct LongShort aliases[]= {
{"01", "http1.1", FALSE}, {"01", "http1.1", FALSE},
{"02", "http2.0", FALSE}, {"02", "http2.0", FALSE},
{"1", "tlsv1", FALSE}, {"1", "tlsv1", FALSE},
{"10", "tlsv1.0", FALSE},
{"11", "tlsv1.1", FALSE},
{"12", "tlsv1.2", FALSE},
{"2", "sslv2", FALSE}, {"2", "sslv2", FALSE},
{"3", "sslv3", FALSE}, {"3", "sslv3", FALSE},
{"4", "ipv4", FALSE}, {"4", "ipv4", FALSE},
@@ -215,6 +218,7 @@ static const struct LongShort aliases[]= {
{"El", "tlspassword", TRUE}, {"El", "tlspassword", TRUE},
{"Em", "tlsauthtype", TRUE}, {"Em", "tlsauthtype", TRUE},
{"En", "ssl-allow-beast", FALSE}, {"En", "ssl-allow-beast", FALSE},
{"Eo", "login-options", TRUE},
{"f", "fail", FALSE}, {"f", "fail", FALSE},
{"F", "form", TRUE}, {"F", "form", TRUE},
{"Fs", "form-string", TRUE}, {"Fs", "form-string", TRUE},
@@ -1023,9 +1027,25 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
break; break;
} }
break; break;
case '1': case '1': /* --tlsv1* options */
/* TLS version 1 */ switch(subletter) {
config->ssl_version = CURL_SSLVERSION_TLSv1; case '\0':
/* TLS version 1.x */
config->ssl_version = CURL_SSLVERSION_TLSv1;
break;
case '0':
/* TLS version 1.0 */
config->ssl_version = CURL_SSLVERSION_TLSv1_0;
break;
case '1':
/* TLS version 1.1 */
config->ssl_version = CURL_SSLVERSION_TLSv1_1;
break;
case '2':
/* TLS version 1.2 */
config->ssl_version = CURL_SSLVERSION_TLSv1_2;
break;
}
break; break;
case '2': case '2':
/* SSL version 2 */ /* SSL version 2 */
@@ -1347,10 +1367,15 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
else else
return PARAM_LIBCURL_DOESNT_SUPPORT; return PARAM_LIBCURL_DOESNT_SUPPORT;
break; break;
case 'n': /* no empty SSL fragments */ case 'n': /* no empty SSL fragments, --ssl-allow-beast */
if(curlinfo->features & CURL_VERSION_SSL) if(curlinfo->features & CURL_VERSION_SSL)
config->ssl_allow_beast = toggle; config->ssl_allow_beast = toggle;
break; break;
case 'o': /* --login-options */
GetStr(&config->login_options, nextarg);
break;
default: /* certificate file */ default: /* certificate file */
{ {
char *certname, *passphrase; char *certname, *passphrase;
@@ -1668,7 +1693,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
} }
break; break;
case 'u': case 'u':
/* user:password;options */ /* user:password */
GetStr(&config->userpwd, nextarg); GetStr(&config->userpwd, nextarg);
cleanarg(nextarg); cleanarg(nextarg);
break; break;

View File

@@ -120,7 +120,7 @@ static const char *const helptext[] = {
" --libcurl FILE Dump libcurl equivalent code of this command line", " --libcurl FILE Dump libcurl equivalent code of this command line",
#endif #endif
" --limit-rate RATE Limit transfer speed to this rate", " --limit-rate RATE Limit transfer speed to this rate",
" -l, --list-only List only names of an FTP directory (F)", " -l, --list-only List only mode (F/POP3)",
" --local-port RANGE Force use of these local port numbers", " --local-port RANGE Force use of these local port numbers",
" -L, --location Follow redirects (H)", " -L, --location Follow redirects (H)",
" --location-trusted like --location and send auth to other hosts (H)", " --location-trusted like --location and send auth to other hosts (H)",
@@ -141,7 +141,7 @@ static const char *const helptext[] = {
" --no-sessionid Disable SSL session-ID reusing (SSL)", " --no-sessionid Disable SSL session-ID reusing (SSL)",
" --noproxy List of hosts which do not use proxy", " --noproxy List of hosts which do not use proxy",
" --ntlm Use HTTP NTLM authentication (H)", " --ntlm Use HTTP NTLM authentication (H)",
" --oauth2-bearer BEARER XOAUTH2 Bearer Token (IMAP, POP3, SMTP)", " --oauth2-bearer TOKEN OAuth 2 Bearer Token (IMAP, POP3, SMTP)",
" -o, --output FILE Write output to <file> instead of stdout", " -o, --output FILE Write output to <file> instead of stdout",
" --pass PASS Pass phrase for the private key (SSL/SSH)", " --pass PASS Pass phrase for the private key (SSL/SSH)",
" --post301 " " --post301 "
@@ -215,7 +215,8 @@ static const char *const helptext[] = {
" -T, --upload-file FILE Transfer FILE to destination", " -T, --upload-file FILE Transfer FILE to destination",
" --url URL URL to work with", " --url URL URL to work with",
" -B, --use-ascii Use ASCII/text transfer", " -B, --use-ascii Use ASCII/text transfer",
" -u, --user USER[:PASSWORD] Server user and password", " -u, --user USER[:PASSWORD][;OPTIONS] Server user, password and login"
" options",
" --tlsuser USER TLS username", " --tlsuser USER TLS username",
" --tlspassword STRING TLS password", " --tlspassword STRING TLS password",
" --tlsauthtype STRING TLS authentication type (default SRP)", " --tlsauthtype STRING TLS authentication type (default SRP)",

View File

@@ -54,9 +54,7 @@
# define MD5_CTX void * # define MD5_CTX void *
# define SHA_CTX void * # define SHA_CTX void *
# define SHA256_CTX void * # define SHA256_CTX void *
# ifdef HAVE_NSS_INITCONTEXT static NSSInitContext *nss_context;
static NSSInitContext *nss_context;
# endif
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
@@ -240,7 +238,6 @@ static int nss_hash_init(void **pctx, SECOidTag hash_alg)
PK11Context *ctx; PK11Context *ctx;
/* we have to initialize NSS if not initialized alraedy */ /* we have to initialize NSS if not initialized alraedy */
#ifdef HAVE_NSS_INITCONTEXT
if(!NSS_IsInitialized() && !nss_context) { if(!NSS_IsInitialized() && !nss_context) {
static NSSInitParameters params; static NSSInitParameters params;
params.length = sizeof params; params.length = sizeof params;
@@ -248,7 +245,6 @@ static int nss_hash_init(void **pctx, SECOidTag hash_alg)
| 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);
} }
#endif
ctx = PK11_CreateDigestContext(hash_alg); ctx = PK11_CreateDigestContext(hash_alg);
if(!ctx) if(!ctx)
@@ -894,7 +890,7 @@ void clean_metalink(struct Configurable *config)
void metalink_cleanup(void) void metalink_cleanup(void)
{ {
#if defined(USE_NSS) && defined(HAVE_NSS_INITCONTEXT) #ifdef USE_NSS
if(nss_context) { if(nss_context) {
NSS_ShutdownContext(nss_context); NSS_ShutdownContext(nss_context);
nss_context = NULL; nss_context = NULL;

View File

@@ -1051,6 +1051,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
my_setopt(curl, CURLOPT_NETRC_FILE, config->netrc_file); my_setopt(curl, CURLOPT_NETRC_FILE, config->netrc_file);
my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L); my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii?1L:0L);
if(config->login_options)
my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd); my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
my_setopt_str(curl, CURLOPT_RANGE, config->range); my_setopt_str(curl, CURLOPT_RANGE, config->range);
my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer); my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
@@ -1235,8 +1237,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
!config->noprogress && !config->mute) { !config->noprogress && !config->mute) {
/* we want the alternative style, then we have to implement it /* we want the alternative style, then we have to implement it
ourselves! */ ourselves! */
my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb); my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); my_setopt(curl, CURLOPT_XFERINFODATA, &progressbar);
} }
/* new in libcurl 7.24.0: */ /* new in libcurl 7.24.0: */

View File

@@ -35,7 +35,10 @@
#include "memdebug.h" /* keep this as LAST include */ #include "memdebug.h" /* keep this as LAST include */
#define CURLRC DOT_CHAR "curlrc" #define CURLRC DOT_CHAR "curlrc"
#define ISSEP(x) (((x) == '=') || ((x) == ':'))
/* only acknowledge colon or equals as separators if the option was not
specified with an initial dash! */
#define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':')))
static const char *unslashquote(const char *line, char *param); static const char *unslashquote(const char *line, char *param);
static char *my_get_line(FILE *fp); static char *my_get_line(FILE *fp);
@@ -123,6 +126,7 @@ int parseconfig(const char *filename,
char *param; char *param;
int lineno = 0; int lineno = 0;
bool alloced_param; bool alloced_param;
bool dashed_option;
while(NULL != (aline = my_get_line(file))) { while(NULL != (aline = my_get_line(file))) {
lineno++; lineno++;
@@ -146,7 +150,11 @@ int parseconfig(const char *filename,
/* the option keywords starts here */ /* the option keywords starts here */
option = line; option = line;
while(*line && !ISSPACE(*line) && !ISSEP(*line))
/* the option starts with a dash? */
dashed_option = option[0]=='-'?TRUE:FALSE;
while(*line && !ISSPACE(*line) && !ISSEP(*line, dashed_option))
line++; line++;
/* ... and has ended here */ /* ... and has ended here */
@@ -158,7 +166,7 @@ int parseconfig(const char *filename,
#endif #endif
/* pass spaces and separator(s) */ /* pass spaces and separator(s) */
while(*line && (ISSPACE(*line) || ISSEP(*line))) while(*line && (ISSPACE(*line) || ISSEP(*line, dashed_option)))
line++; line++;
/* the parameter starts here (unless quoted) */ /* the parameter starts here (unless quoted) */
@@ -180,6 +188,24 @@ int parseconfig(const char *filename,
while(*line && !ISSPACE(*line)) while(*line && !ISSPACE(*line))
line++; line++;
*line = '\0'; /* zero terminate */ *line = '\0'; /* zero terminate */
/* to detect mistakes better, see if there's data following */
line++;
/* pass all spaces */
while(*line && ISSPACE(*line))
line++;
switch(*line) {
case '\0':
case '\r':
case '\n':
case '#': /* comment */
break;
default:
warnf(config, "%s:%d: warning: '%s' uses unquoted white space in the"
" line that may cause side-effects!\n",
filename, lineno, option);
}
} }
if(param && !*param) { if(param && !*param) {

View File

@@ -78,6 +78,9 @@ const NameValue setopt_nv_CURL_SSLVERSION[] = {
NV(CURL_SSLVERSION_TLSv1), NV(CURL_SSLVERSION_TLSv1),
NV(CURL_SSLVERSION_SSLv2), NV(CURL_SSLVERSION_SSLv2),
NV(CURL_SSLVERSION_SSLv3), NV(CURL_SSLVERSION_SSLv3),
NV(CURL_SSLVERSION_TLSv1_0),
NV(CURL_SSLVERSION_TLSv1_1),
NV(CURL_SSLVERSION_TLSv1_2),
NVEND, NVEND,
}; };

View File

@@ -40,7 +40,7 @@ typedef enum {
void glob_cleanup(URLGlob* glob); void glob_cleanup(URLGlob* glob);
static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount) static GlobCode glob_fixed(URLGlob *glob, char *fixed, size_t len)
{ {
URLPattern *pat = &glob->pattern[glob->size]; URLPattern *pat = &glob->pattern[glob->size];
pat->type = UPTSet; pat->type = UPTSet;
@@ -48,17 +48,18 @@ static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
pat->content.Set.ptr_s = 0; pat->content.Set.ptr_s = 0;
pat->globindex = -1; pat->globindex = -1;
(*amount)++;
pat->content.Set.elements = malloc(sizeof(char*)); pat->content.Set.elements = malloc(sizeof(char*));
if(!pat->content.Set.elements) if(!pat->content.Set.elements)
return GLOBERROR("out of memory", 0, GLOB_NO_MEM); return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
pat->content.Set.elements[0] = strdup(glob->glob_buffer); pat->content.Set.elements[0] = malloc(len+1);
if(!pat->content.Set.elements[0]) if(!pat->content.Set.elements[0])
return GLOBERROR("out of memory", 0, GLOB_NO_MEM); return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
memcpy(pat->content.Set.elements[0], fixed, len);
pat->content.Set.elements[0][len] = 0;
return GLOB_OK; return GLOB_OK;
} }
@@ -211,7 +212,7 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
} }
} }
else else
pattern+=3; pattern += 4;
*posp += (pattern - *patternp); *posp += (pattern - *patternp);
@@ -307,11 +308,13 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
/* processes a literal string component of a URL /* processes a literal string component of a URL
special characters '{' and '[' branch to set/range processing functions special characters '{' and '[' branch to set/range processing functions
*/ */
char* buf = glob->glob_buffer;
GlobCode res = GLOB_OK; GlobCode res = GLOB_OK;
int globindex = 0; /* count "actual" globs */ int globindex = 0; /* count "actual" globs */
*amount = 1;
while(*pattern && !res) { while(*pattern && !res) {
char *buf = glob->glob_buffer;
int sublen = 0; int sublen = 0;
while(*pattern && *pattern != '{' && *pattern != '[') { while(*pattern && *pattern != '{' && *pattern != '[') {
if(*pattern == '}' || *pattern == ']') if(*pattern == '}' || *pattern == ']')
@@ -333,12 +336,9 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
if(sublen) { if(sublen) {
/* we got a literal string, add it as a single-item list */ /* we got a literal string, add it as a single-item list */
*buf = '\0'; *buf = '\0';
res = glob_fixed(glob, amount); res = glob_fixed(glob, glob->glob_buffer, sublen);
} }
else { else {
if(!*amount)
*amount = 1;
switch (*pattern) { switch (*pattern) {
case '\0': /* done */ case '\0': /* done */
break; break;

View File

@@ -3,6 +3,8 @@
# per line. # per line.
# Lines starting with '#' letters are treated as comments. # Lines starting with '#' letters are treated as comments.
594 594
815
816
1209 1209
1211 1211
1512 1512

View File

@@ -64,14 +64,19 @@ test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 \ test709 test710 test711 test712 \
\ \
test800 test801 test802 test803 test804 test805 test806 test807 test808 \ test800 test801 test802 test803 test804 test805 test806 test807 test808 \
test809 test810 test811 test812 test813 test814 \ test809 test810 test811 test812 test813 test814 test815 test816 test817 \
test818 test819 test820 test821 test822 test823 test824 test825 test826 \
test827 test828 test829 test830 test831 test832 \
\ \
test850 test851 test852 test853 test854 test855 test856 test857 test858 \ test850 test851 test852 test853 test854 test855 test856 test857 test858 \
test859 test860 test861 test862 \ test859 test860 test861 test862 test863 test864 test865 test866 test867 \
test868 test869 test870 test871 test872 test873 test874 test875 test876 \
test877 test878 \
\ \
test900 test901 test902 test903 test904 test905 test906 test907 test908 \ test900 test901 test902 test903 test904 test905 test906 test907 test908 \
test909 test910 test911 test912 test913 test914 test915 test916 test917 \ test909 test910 test911 test912 test913 test914 test915 test916 test917 \
test918 \ test918 test919 test920 test921 test922 test923 test924 test925 test926 \
test927 test928 test929 test930 test931 test932 test933 test934 \
\ \
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \ test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \ test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -96,12 +101,12 @@ test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \ test1216 test1217 test1218 test1219 \
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \ test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \ test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
test1236 test1237 test1238 test1239 \ test1236 test1237 test1238 test1239 test1240 \
\ \
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \ test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \ test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
test1316 test1317 test1318 test1319 test1320 test1321 test1322 test1323 \ test1316 test1317 test1318 test1319 test1320 test1321 \
test1324 test1325 test1326 test1327 test1328 test1329 test1330 test1331 \ test1325 test1326 test1327 test1328 test1329 test1330 test1331 \
test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 \ test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 \
test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 \ test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 \
test1348 test1349 test1350 test1351 test1352 test1353 test1354 test1355 \ test1348 test1349 test1350 test1351 test1352 test1353 test1354 test1355 \

48
tests/data/test1240 Normal file
View File

@@ -0,0 +1,48 @@
<testcase>
<info>
<keywords>
globbing
HTTP
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 200 OK
Content-Length: 6
Connection: close
-foo-
</data>
</reply>
# Client-side
<client>
<server>
http
</server>
<name>
glob [0-1] with stuff after range (7.33.0 regression)
</name>
<command>
"%HOSTIP:%HTTPPORT/0[0-1]/1240"
</command>
</client>
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /00/1240 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
GET /01/1240 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
</verify>
</testcase>

View File

@@ -27,7 +27,7 @@ imap
IMAP doesn't perform SELECT if re-using the same mailbox IMAP doesn't perform SELECT if re-using the same mailbox
</name> </name>
<command> <command>
-u user:secret 'imap://%HOSTIP:%IMAPPORT/804/;UID=123/;SECTION=1' 'imap://%HOSTIP:%IMAPPORT/804/;UID=456/;SECTION=2.3' 'imap://%HOSTIP:%IMAPPORT/804/;UID=123/;SECTION=1' 'imap://%HOSTIP:%IMAPPORT/804/;UID=456/;SECTION=2.3' -u user:secret
</command> </command>
</client> </client>

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