Compare commits
246 Commits
curl-7_33_
...
curl-7_34_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0966b324d9 | ||
|
|
c0ef05e675 | ||
|
|
1dc43de0dc | ||
|
|
8a8f9a5d57 | ||
|
|
be28223f35 | ||
|
|
8e2d73bbde | ||
|
|
dd4d9ea542 | ||
|
|
169fedbdce | ||
|
|
32b9c30e67 | ||
|
|
75cd7fd667 | ||
|
|
7246dffff5 | ||
|
|
41d21e460f | ||
|
|
aadca7f418 | ||
|
|
3905bd637d | ||
|
|
c4f46e97ca | ||
|
|
bd3ca6630a | ||
|
|
92e607abfa | ||
|
|
ef118c13ba | ||
|
|
1cf71bd76e | ||
|
|
2c0ecac9d3 | ||
|
|
b0b5b51193 | ||
|
|
ff9b66a8d4 | ||
|
|
e221b55f67 | ||
|
|
865666afca | ||
|
|
7fc9325a52 | ||
|
|
4fb8241add | ||
|
|
30e7e7552b | ||
|
|
f58f843f66 | ||
|
|
d92de3a7e9 | ||
|
|
fe7fc61c6e | ||
|
|
ad3836448e | ||
|
|
f3ee587775 | ||
|
|
c92c30edbd | ||
|
|
4d10f48629 | ||
|
|
dc68120e63 | ||
|
|
0db811b69b | ||
|
|
d81cbbcc2c | ||
|
|
0dd6522036 | ||
|
|
889cb9c982 | ||
|
|
26ff1ea6c3 | ||
|
|
59f1209fad | ||
|
|
7b9365c65f | ||
|
|
a900d45489 | ||
|
|
e64f91feb7 | ||
|
|
b2a55c8106 | ||
|
|
030a2b8cb8 | ||
|
|
edce855943 | ||
|
|
35e476a3f6 | ||
|
|
0434a19431 | ||
|
|
2ff0c6f5f3 | ||
|
|
8a94aedbd6 | ||
|
|
95877cf8ae | ||
|
|
d3325ae40a | ||
|
|
23fabf8dea | ||
|
|
7a36b2abc0 | ||
|
|
e1c255f388 | ||
|
|
6d3c832a30 | ||
|
|
7935478397 | ||
|
|
5ee64be9c6 | ||
|
|
9f18cf15d5 | ||
|
|
bf05da183e | ||
|
|
2c04e8d80c | ||
|
|
925df53580 | ||
|
|
8191800a0c | ||
|
|
2165298fe6 | ||
|
|
e885dc85a1 | ||
|
|
df58084695 | ||
|
|
3c8c9b2779 | ||
|
|
b27dc009cf | ||
|
|
2c7a5578e1 | ||
|
|
b56d7cda74 | ||
|
|
8896b56488 | ||
|
|
0d735c29f9 | ||
|
|
3d50e91aee | ||
|
|
0cbfe5a7d5 | ||
|
|
eedca5055e | ||
|
|
5d040632ac | ||
|
|
314c3b8480 | ||
|
|
d630e1f389 | ||
|
|
0ea4a80bb2 | ||
|
|
ed4ce23c23 | ||
|
|
168aa59705 | ||
|
|
f71b1ad908 | ||
|
|
dac01ff6d7 | ||
|
|
4a9fe26837 | ||
|
|
90ec8763a5 | ||
|
|
796333bc5e | ||
|
|
f16c0de4e9 | ||
|
|
786cba1ada | ||
|
|
ed1662c374 | ||
|
|
1f0616ea1a | ||
|
|
55250d2d02 | ||
|
|
c5d73167a6 | ||
|
|
bde901ad89 | ||
|
|
79c77f7c31 | ||
|
|
986c249f2f | ||
|
|
3b8c3eb911 | ||
|
|
b29217d0d6 | ||
|
|
534f90f9bf | ||
|
|
dbe228353d | ||
|
|
bf77101e5c | ||
|
|
2ea9a125a6 | ||
|
|
58a00d6d9f | ||
|
|
57a27528e6 | ||
|
|
632c1edd06 | ||
|
|
434bc09263 | ||
|
|
f2584627c8 | ||
|
|
6901861fc9 | ||
|
|
d7d8a8f922 | ||
|
|
c19cfb79db | ||
|
|
65ce9b6d6c | ||
|
|
5f34a10445 | ||
|
|
fa1253aee1 | ||
|
|
f833f54979 | ||
|
|
e7d77fb3ef | ||
|
|
c8e63f247a | ||
|
|
7396ad6e09 | ||
|
|
6d295f8d7d | ||
|
|
5bd999d0c5 | ||
|
|
0f81fbe5da | ||
|
|
9b67960421 | ||
|
|
e10a26a9d6 | ||
|
|
7b68b58bc0 | ||
|
|
2d5455feac | ||
|
|
ac05c80f19 | ||
|
|
460adfef93 | ||
|
|
c876f6ae6d | ||
|
|
f49276bfcb | ||
|
|
d08ee3c83d | ||
|
|
cf7008670b | ||
|
|
558034ab70 | ||
|
|
27b7b1062f | ||
|
|
af82661dbd | ||
|
|
76f924131c | ||
|
|
98a5fdaf29 | ||
|
|
1ea05be46d | ||
|
|
c9d8c00a41 | ||
|
|
5aa290f0f2 | ||
|
|
f0831f7931 | ||
|
|
7fc3b2ce38 | ||
|
|
02fbc26d59 | ||
|
|
0074c9f5d1 | ||
|
|
90acbfd52e | ||
|
|
989b28fe97 | ||
|
|
aa61e14dc1 | ||
|
|
a84a09ad0b | ||
|
|
66b8557aff | ||
|
|
63cac69c2a | ||
|
|
f77d9b6584 | ||
|
|
2736b27df7 | ||
|
|
297644fa70 | ||
|
|
0177f28c51 | ||
|
|
732d10ed6c | ||
|
|
526a1c3b45 | ||
|
|
5b315a273e | ||
|
|
5094bb53f4 | ||
|
|
052f24c9b7 | ||
|
|
bce03fe144 | ||
|
|
9a1755264f | ||
|
|
3b59696a93 | ||
|
|
cdccb42267 | ||
|
|
753d44fa00 | ||
|
|
cfdfdcdd9d | ||
|
|
e232f5f3f9 | ||
|
|
43400b4086 | ||
|
|
8179354c2f | ||
|
|
f6c335d63f | ||
|
|
2bd72fa61c | ||
|
|
e17c1b25bc | ||
|
|
7d1eb66cd7 | ||
|
|
255826c40f | ||
|
|
1d0eead969 | ||
|
|
8005e58983 | ||
|
|
5d415815df | ||
|
|
f68559c086 | ||
|
|
08f97f3b1d | ||
|
|
b87ba2c942 | ||
|
|
e7a2ba41e3 | ||
|
|
6fe619be7a | ||
|
|
1e39b95682 | ||
|
|
8230af0b94 | ||
|
|
1709e5e966 | ||
|
|
7d7df83198 | ||
|
|
7de4cc35f8 | ||
|
|
aa0eaef483 | ||
|
|
9f503a254b | ||
|
|
d44b014271 | ||
|
|
469b423350 | ||
|
|
0adad07690 | ||
|
|
e4670a1029 | ||
|
|
1f0e50f2b9 | ||
|
|
2766262a68 | ||
|
|
bdb1f0e53d | ||
|
|
6e3613e6e6 | ||
|
|
1cb5150dba | ||
|
|
d24b7953c2 | ||
|
|
13db74ffc3 | ||
|
|
98905aa2c5 | ||
|
|
820ed48a00 | ||
|
|
973cc22529 | ||
|
|
2cc9246477 | ||
|
|
650036633f | ||
|
|
78aee26be6 | ||
|
|
947d431d50 | ||
|
|
58bd0148fb | ||
|
|
ca5c5be3e4 | ||
|
|
9bd37a6d27 | ||
|
|
1be69159f3 | ||
|
|
a3da0a96e3 | ||
|
|
626f8a85f0 | ||
|
|
867b52a7ac | ||
|
|
be31924f8c | ||
|
|
f70b2c77f4 | ||
|
|
ae495ffcc3 | ||
|
|
0fdfe82c6a | ||
|
|
dead10b1b8 | ||
|
|
41d820d2c3 | ||
|
|
5b31b38c27 | ||
|
|
39f4e4fafa | ||
|
|
587811c0a6 | ||
|
|
7f7fbe7fbd | ||
|
|
9b1eb2b421 | ||
|
|
1034aa6680 | ||
|
|
4be0af7f74 | ||
|
|
72f850571d | ||
|
|
e179d0eb12 | ||
|
|
ce61510127 | ||
|
|
86c64f3daf | ||
|
|
65e556d0ce | ||
|
|
6a1363128f | ||
|
|
75b9b26465 | ||
|
|
2c84ffe154 | ||
|
|
e7452415c5 | ||
|
|
87861c9b0e | ||
|
|
4d49ffe165 | ||
|
|
f63603dec4 | ||
|
|
0218a737fe | ||
|
|
18ca0aa984 | ||
|
|
c4e6c33b13 | ||
|
|
d774802eec | ||
|
|
69c0d3fbc8 | ||
|
|
076726f141 | ||
|
|
ad34a2d5c8 | ||
|
|
31e106c01c | ||
|
|
1dcc433661 | ||
|
|
a106abee62 |
11
.travis.yml
Normal file
11
.travis.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
language: c
|
||||
|
||||
before_script:
|
||||
- ./buildconf
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -108,7 +108,11 @@ if(NOT UNIX)
|
||||
set(HAVE_IN_ADDR_T 0)
|
||||
set(HAVE_INET_NTOA_R_DECL 0)
|
||||
set(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
|
||||
if(ENABLE_IPV6)
|
||||
set(HAVE_GETADDRINFO 1)
|
||||
else()
|
||||
set(HAVE_GETADDRINFO 0)
|
||||
endif()
|
||||
set(STDC_HEADERS 1)
|
||||
set(RETSIGTYPE_TEST 1)
|
||||
|
||||
|
||||
@@ -783,6 +783,17 @@ else()
|
||||
set(CURL_SIZEOF_CURL_SOCKLEN_T ${SIZEOF_INT})
|
||||
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)
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
180
RELEASE-NOTES
180
RELEASE-NOTES
@@ -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
|
||||
curl_easy_setopt() options: 205
|
||||
curl_easy_setopt() options: 206
|
||||
Public functions in libcurl: 58
|
||||
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:
|
||||
|
||||
o test code for testing the event based API [3]
|
||||
o CURLM_ADDED_ALREADY: new error code
|
||||
o test TFTP server: support "writedelay" within <servercmd>
|
||||
o krb4 support has been removed
|
||||
o imap/pop3/smtp: added basic SASL XOAUTH2 support [9]
|
||||
o darwinssl: add support for PKCS#12 files for client authentication
|
||||
o darwinssl: enable BEAST workaround on iOS 7 & later
|
||||
o Pass password to OpenSSL engine by user interface [15]
|
||||
o c-ares: Add support for various DNS binding options
|
||||
o cookies: add expiration
|
||||
o curl: added --oauth2-bearer option
|
||||
o SSL: protocol version can be specified more precisely [1]
|
||||
o imap/pop3/smtp: Added graceful cancellation of SASL authentication
|
||||
o Add "Happy Eyeballs" for IPv4/IPv6 dual connect attempts
|
||||
o base64: Added validation of base64 input strings when decoding [8]
|
||||
o curl_easy_setopt: Added the ability to set the login options separately
|
||||
o smtp: Added support for additional SMTP commands
|
||||
o curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals
|
||||
o nss: allow to use TLS > 1.0 if built against recent NSS [18]
|
||||
o SECURITY: added this document to describe our security processes [22]
|
||||
o parseconfig: warn if unquoted white spaces are detected
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o nss: make sure that NSS is initialized
|
||||
o curl: make --no-[option] work properly for several options
|
||||
o FTP: with socket_action send better socket updates in active mode [1]
|
||||
o curl: fix the --sasl-ir in the --help output
|
||||
o tests 2032, 2033: Don't hardcode port in expected output
|
||||
o urlglob: better detect unclosed braces, empty lists and overflows [7]
|
||||
o urlglob: error out on range overflow [8]
|
||||
o imap: Fixed response check for SEARCH, EXPUNGE, LSUB, UID and NOOP commands [10]
|
||||
o handle arbitrary-length username and password [2]
|
||||
o TFTP: make the CURLOPT_LOW_SPEED* options work [4]
|
||||
o curl.h: name space pollution by "enum type" [5]
|
||||
o multi: move on from STATE_DONE faster [6]
|
||||
o FTP: 60 secs delay if aborted in the CURLOPT_HEADERFUNCTION callback [11]
|
||||
o multi_socket: improved 100-continue timeout handling
|
||||
o curl_multi_remove_handle: allow multiple removes
|
||||
o FTP: fix getsock during DO_MORE state [12]
|
||||
o -x: rephrased the --proxy section somewhat
|
||||
o acinclude: fix --without-ca-path when cross-compiling [13]
|
||||
o LDAP: fix bad free() when URL parsing failed [14]
|
||||
o --data: mention CRLF treatment when reading from file
|
||||
o curl_easy_pause: suggest one way to unpause
|
||||
o imap: Fixed calculation of transfer when partial FETCH received [16]
|
||||
o pingpong: Check SSL library buffers for already read data [16]
|
||||
o imap/pop3/smtp: Speed up SSL connection initialization
|
||||
o libcurl.3: for multi interface connections are held in the multi handle
|
||||
o curl_easy_setopt.3: mention RTMP URL quirks [17]
|
||||
o curl.1: detail how short/long options work [18]
|
||||
o curl.1: Added information about optional login options to --user option
|
||||
o curl: Added clarification to the --mail options in the --help output
|
||||
o curl_easy_setopt.3: clarify that TIMEOUT and TIMEOUT_MS set the same value
|
||||
o openssl: use correct port number in error message [19]
|
||||
o darwinssl: block TLS_RSA_WITH_NULL_SHA256 cipher
|
||||
o OpenSSL: acknowledge CURLOPT_SSL_VERIFYHOST without VERIFYPEER
|
||||
o xattr: add support for FreeBSD xattr API
|
||||
o win32: fix Visual Studio 2010 build with WINVER >= 0x600 [22]
|
||||
o configure: use icc options without space [21]
|
||||
o test1112: Increase the timeout from 7s to 16s [20]
|
||||
o SCP: upload speed on a fast connection limited to 16384 B/s
|
||||
o curl_setup_once: fix errno access for lwip on Windows [24]
|
||||
o HTTP: Output http response 304 when modified time is too old [23]
|
||||
o darwinssl: un-break iOS build after PKCS#12 feature added
|
||||
o tool: use XFERFUNCTION to save some casts [2]
|
||||
o usercertinmem: fix memory leaks
|
||||
o ssh: Handle successful SSH_USERAUTH_NONE [3]
|
||||
o NSS: acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option [4]
|
||||
o test906: Fixed failing test on some platforms [5]
|
||||
o sasl: initialize NSS before using NTLM crypto
|
||||
o sasl: Fixed memory leak in OAUTH2 message creation
|
||||
o imap/pop3/smtp: Fixed QUIT / LOGOUT being sent when SSL connect fails
|
||||
o cmake: unbreak for non-Windows platforms [6]
|
||||
o ssh: initialize per-handle data in ssh_connect()
|
||||
o glob: fix broken URLs
|
||||
o configure: check for long long when building with cyassl
|
||||
o CURLOPT_RESOLVE: mention they don't time-out [7]
|
||||
o docs/examples/httpput.c: fix build for MSVC
|
||||
o FTP: make the data connection work when going through proxy
|
||||
o NSS: support for CERTINFO feature
|
||||
o curl_multi_wait: accept 0 from multi_timeout() as valid timeout
|
||||
o glob_range: pass the closing bracket for a-z ranges
|
||||
o tool_help: Updated --list-only description to include POP3
|
||||
o Curl_ssl_push_certinfo_len: don't %.*s non-zero-terminated string [9]
|
||||
o cmake: fix Windows build with IPv6 support [10]
|
||||
o ares: Fixed compilation under Visual Studio 2012 [11]
|
||||
o curl_easy_setopt.3: clarify CURLOPT_SSL_VERIFYHOST documentation [12]
|
||||
o curl.1: mention that -O does no URL decoding [13]
|
||||
o darwinssl: PKCS#12 import feature now requires Lion or later [14]
|
||||
o darwinssl: check for SSLSetSessionOption() presence when toggling BEAST
|
||||
o configure: Fix test with -Werror=implicit-function-declaration [15]
|
||||
o sigpipe: factor out sigpipe_reset from easy.c
|
||||
o curl_multi_cleanup: ignore SIGPIPE
|
||||
o globbing: curl glob counter mismatch with {} list use [16]
|
||||
o parseconfig: dash options can't specified with colon or equals [17]
|
||||
o digest: fix CURLAUTH_DIGEST_IE [19]
|
||||
o curl.h: <sys/select.h> for OpenBSD [20]
|
||||
o darwinssl: Fix #if 10.6.0 for SecKeychainSearch
|
||||
o TFTP: fix return codes for connect timeout [21]
|
||||
o login options: remove the ;[options] support from CURLOPT_USERPWD [23]
|
||||
o imap: Fixed incorrect fallback to clear text authentication
|
||||
o parsedate: avoid integer overflow
|
||||
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:
|
||||
|
||||
@@ -71,41 +74,42 @@ This release includes the following known bugs:
|
||||
This release would not have looked like this without help, code, reports and
|
||||
advice from friends like these:
|
||||
|
||||
Alex McLellan, Bill Doyle, Colby Ranger, Fabian Keil, Gisle Vanem,
|
||||
John E. Malmberg, Jonathan Nieder, Kamil Dudka, Shawn Landden,
|
||||
Tor Arntsen, Will Dietz, Yi Huang, Kyle L. Huff, Steve Holme, Mike Mio,
|
||||
Stefan Neis, Nick Zitzmann, Geoff Beier, John Dunn, Jiri Hruska,
|
||||
Tomas Mlcoch, Kim Vandry, Ben Greear, Gorilla Maguila, Jerry Krinock,
|
||||
Yamada Yasuharu, Gordon Marler, Dave Thompson, D. Flinkmann,
|
||||
Benoit Sigoure, Clemens Gruber, Guenter Knauf, Petr Pisar, Elmira A Semenova,
|
||||
Francois Charlier, Ishan SinghLevett, Marcel Raad, Ulf Samuelsson,
|
||||
Andrej E Baranov, Derek Higgins, Heinrich Schaefer
|
||||
Alessandro Ghedini, Andreas Rieke, Björn Stenberg, Chris Conlon,
|
||||
Christian Grothoff, Christian Weisgerber, Dave Reisner, David Walser,
|
||||
Dima Tisnek, Fabian Keil, Felix Yan, Gergely Nagy, Gisle Vanem,
|
||||
Ishan SinghLevett, James Dury, Javier Barroso, Jeff King, Kamil Dudka,
|
||||
Kim Vandry, Marcin Gryszkalis, Melissa Mears, Michael Osipov, Nick Zitzmann,
|
||||
Oliver Kuckertz, Patrick Monnerat, Paul Donohue, Paul Marks, Romulo A. Ceccon,
|
||||
Rémy Léone, Sergey Tatarincev, Steve Holme, Tomas Hoger, Tyler Hall,
|
||||
Yaakov Selkowitz, Eric Lubin, Petr Bahula, He Qin, Marc Deslauriers
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
|
||||
[1] = http://curl.haxx.se/mail/lib-2013-08/0043.html
|
||||
[2] = http://bugs.debian.org/719856
|
||||
[3] = http://daniel.haxx.se/blog/2013/08/20/testing-curl_multi_socket_action/
|
||||
[4] = http://curl.haxx.se/bug/view.cgi?id=1269
|
||||
[5] = https://github.com/bagder/curl/pull/76
|
||||
[6] = http://curl.haxx.se/mail/lib-2013-08/0211.html
|
||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1264
|
||||
[8] = http://curl.haxx.se/bug/view.cgi?id=1267
|
||||
[9] = http://curl.haxx.se/mail/lib-2013-08/0234.html
|
||||
[10] = http://curl.haxx.se/mail/lib-2013-08/0136.html
|
||||
[11] = https://bugzilla.redhat.com/1005686
|
||||
[12] = http://curl.haxx.se/mail/lib-2013-08/0109.html
|
||||
[13] = http://curl.haxx.se/bug/view.cgi?id=1273
|
||||
[14] = http://curl.haxx.se/mail/lib-2013-08/0209.html
|
||||
[15] = http://curl.haxx.se/mail/lib-2013-08/0265.html
|
||||
[16] = http://curl.haxx.se/mail/lib-2013-08/0170.html
|
||||
[17] = http://curl.haxx.se/bug/view.cgi?id=1278
|
||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1279
|
||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1281
|
||||
[20] = http://curl.haxx.se/mail/lib-2010-02/0200.html
|
||||
[21] = http://curl.haxx.se/mail/lib-2013-09/0182.html
|
||||
[22] = http://curl.haxx.se/bug/view.cgi?id=1282
|
||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1288
|
||||
[24] = http://curl.haxx.se/mail/lib-2013-10/0048.html
|
||||
[1] = https://github.com/bagder/curl/pull/79
|
||||
[2] = http://curl.haxx.se/mail/lib-2013-10/0089.html
|
||||
[3] = http://curl.haxx.se/mail/lib-2013-10/0096.html
|
||||
[4] = http://curl.haxx.se/mail/lib-2013-10/0113.html
|
||||
[5] = http://sourceforge.net/p/curl/bugs/1291
|
||||
[6] = http://sourceforge.net/p/curl/bugs/1292
|
||||
[7] = http://curl.haxx.se/mail/lib-2013-10/0062.html
|
||||
[8] = http://curl.haxx.se/mail/lib-2013-10/0242.html
|
||||
[9] = http://curl.haxx.se/bug/view.cgi?id=1295
|
||||
[10] = http://sourceforge.net/p/curl/bugs/1064
|
||||
[11] = http://curl.haxx.se/mail/lib-2013-11/0057.html
|
||||
[12] = https://github.com/bagder/curl/pull/83
|
||||
[13] = http://sourceforge.net/p/curl/bugs/1299
|
||||
[14] = http://curl.haxx.se/mail/lib-2013-11/0076.html
|
||||
[15] = http://curl.haxx.se/bug/view.cgi?id=1304
|
||||
[16] = http://curl.haxx.se/bug/view.cgi?id=1305
|
||||
[17] = http://curl.haxx.se/bug/view.cgi?id=1297
|
||||
[18] = http://curl.haxx.se/mail/lib-2013-11/0162.html
|
||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1308
|
||||
[20] = http://curl.haxx.se/mail/lib-2013-12/0017.html
|
||||
[21] = http://curl.haxx.se/bug/view.cgi?id=1310
|
||||
[22] = http://curl.haxx.se/dev/security.html
|
||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1311
|
||||
[24] = http://curl.haxx.se/bug/view.cgi?id=1298
|
||||
[25] = http://curl.haxx.se/bug/view.cgi?id=1294
|
||||
[26] = http://curl.haxx.se/docs/adv_20131217.html
|
||||
|
||||
16
configure.ac
16
configure.ac
@@ -1065,6 +1065,7 @@ AC_HELP_STRING([--disable-ipv6],[Disable ipv6 support]),
|
||||
AC_TRY_RUN([ /* is AF_INET6 available? */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h> /* for exit() */
|
||||
main()
|
||||
{
|
||||
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
|
||||
AC_MSG_NOTICE([detected CyaSSL])
|
||||
|
||||
dnl cyassl/ctaocrypt/types.h needs SIZEOF_LONG_LONG defined!
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
|
||||
LIBS="-lcyassl -lm $LIBS"
|
||||
|
||||
if test -n "$cyassllib"; then
|
||||
@@ -2067,8 +2071,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
|
||||
CPPFLAGS="$CPPFLAGS $addcflags"
|
||||
fi
|
||||
|
||||
dnl The function PK11_CreateGenericObject is needed to load libnsspem.so
|
||||
AC_CHECK_LIB(nss3, PK11_CreateGenericObject,
|
||||
dnl The function SSL_VersionRangeSet() is needed to enable TLS > 1.0
|
||||
AC_CHECK_LIB(nss3, SSL_VersionRangeSet,
|
||||
[
|
||||
AC_DEFINE(USE_NSS, 1, [if NSS is enabled])
|
||||
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
|
||||
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 linker doesn't search through, we need to add it to
|
||||
dnl LD_LIBRARY_PATH to prevent further configure tests to fail
|
||||
|
||||
@@ -43,7 +43,7 @@ Portability
|
||||
openldap 2.0
|
||||
MIT krb5 lib 1.2.4
|
||||
qsossl V5R3M0
|
||||
NSS 3.12.x
|
||||
NSS 3.14.x
|
||||
axTLS 1.2.7
|
||||
Heimdal ?
|
||||
|
||||
|
||||
@@ -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
|
||||
may have been fixed since this was written!
|
||||
|
||||
87. -J/--remote-header-name doesn't decode %-encoded file names. RFC6266
|
||||
details how it should be done. The can of worm is basically that we have no
|
||||
charset handling in curl and ascii >=128 is a challenge for us. Not to
|
||||
mention that decoding also means that we need to check for nastyness that is
|
||||
attempted, like "../" sequences and the like. Probably everything to the left
|
||||
of any embedded slashes should be cut off.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1294
|
||||
|
||||
86. The disconnect commands (LOGOUT and QUIT) may not be sent by IMAP, POP3
|
||||
and SMTP if a failure occures during the authentication phase of a
|
||||
connection.
|
||||
|
||||
85. Wrong STARTTRANSFER timer accounting for POST requests
|
||||
Timer works fine with GET requests, but while using POST the time for
|
||||
CURLINFO_STARTTRANSFER_TIME is wrong. While using POST
|
||||
CURLINFO_STARTTRANSFER_TIME minus CURLINFO_PRETRANSFER_TIME is near to zero
|
||||
every time.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1213
|
||||
|
||||
84. CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
|
||||
backends, so relying on this information in a generic app is flaky.
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ EXTRA_DIST = MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS SSLCERTS \
|
||||
README.win32 RESOURCES TODO TheArtOfHttpScripting THANKS VERSIONS \
|
||||
KNOWN_BUGS BINDINGS $(man_MANS) $(HTMLPAGES) HISTORY INSTALL \
|
||||
$(PDFPAGES) LICENSE-MIXING README.netware DISTRO-DILEMMA INSTALL.devcpp \
|
||||
MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS
|
||||
MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS SECURITY
|
||||
|
||||
MAN2HTML= roffit < $< >$@
|
||||
|
||||
|
||||
91
docs/SECURITY
Normal file
91
docs/SECURITY
Normal 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
|
||||
47
docs/THANKS
47
docs/THANKS
@@ -27,6 +27,7 @@ Alessandro Vesely
|
||||
Alex Bligh
|
||||
Alex Fishman
|
||||
Alex Gruz
|
||||
Alex McLellan
|
||||
Alex Neblett
|
||||
Alex Suykov
|
||||
Alex Vinnik
|
||||
@@ -62,6 +63,7 @@ Andreas Schuldei
|
||||
Andreas Wurf
|
||||
Andrei Benea
|
||||
Andrei Cipu
|
||||
Andrej E Baranov
|
||||
Andres Garcia
|
||||
Andrew Benham
|
||||
Andrew Biggs
|
||||
@@ -109,9 +111,11 @@ Benbuck Nason
|
||||
Benjamin Gerard
|
||||
Benjamin Gilbert
|
||||
Benjamin Johnson
|
||||
Benoit Sigoure
|
||||
Bernard Leak
|
||||
Bernhard Reutner-Fischer
|
||||
Bertrand Demiddelaer
|
||||
Bill Doyle
|
||||
Bill Egert
|
||||
Bill Hoffman
|
||||
Bill Middlecamp
|
||||
@@ -154,6 +158,7 @@ Charles Kerr
|
||||
Chih-Chung Chang
|
||||
Chris "Bob Bob"
|
||||
Chris Combes
|
||||
Chris Conlon
|
||||
Chris Conroy
|
||||
Chris Deidun
|
||||
Chris Flerackers
|
||||
@@ -181,6 +186,7 @@ Clarence Gardner
|
||||
Clemens Gruber
|
||||
Clifford Wolf
|
||||
Cody Jones
|
||||
Colby Ranger
|
||||
Colin Hogben
|
||||
Colin Watson
|
||||
Colm Buckley
|
||||
@@ -194,6 +200,7 @@ Cristian Rodríguez
|
||||
Curt Bogmine
|
||||
Cyrill Osterwalder
|
||||
Cédric Deltheil
|
||||
D. Flinkmann
|
||||
Dag Ekengren
|
||||
Dagobert Michelsen
|
||||
Damien Adant
|
||||
@@ -221,6 +228,7 @@ Dave Halbakken
|
||||
Dave Hamilton
|
||||
Dave May
|
||||
Dave Reisner
|
||||
Dave Thompson
|
||||
Dave Vasilevsky
|
||||
David Bau
|
||||
David Binderman
|
||||
@@ -244,13 +252,16 @@ David Shaw
|
||||
David Strauss
|
||||
David Tarendash
|
||||
David Thiel
|
||||
David Walser
|
||||
David Wright
|
||||
David Yan
|
||||
Dengminwen
|
||||
Derek Higgins
|
||||
Detlef Schmier
|
||||
Didier Brisebourg
|
||||
Diego Casorran
|
||||
Dima Barsky
|
||||
Dima Tisnek
|
||||
Dimitre Dimitrov
|
||||
Dimitris Sarris
|
||||
Dinar
|
||||
@@ -289,6 +300,7 @@ Eelco Dolstra
|
||||
Eetu Ojanen
|
||||
Eldar Zaitov
|
||||
Ellis Pritchard
|
||||
Elmira A Semenova
|
||||
Emanuele Bovisio
|
||||
Emil Romanus
|
||||
Emiliano Ida
|
||||
@@ -298,6 +310,7 @@ Eric Cooper
|
||||
Eric Hu
|
||||
Eric Landes
|
||||
Eric Lavigne
|
||||
Eric Lubin
|
||||
Eric Melville
|
||||
Eric Mertens
|
||||
Eric Rautman
|
||||
@@ -318,10 +331,12 @@ Fabian Hiernaux
|
||||
Fabian Keil
|
||||
Fabrizio Ammollo
|
||||
Fedor Karpelevitch
|
||||
Felix Yan
|
||||
Felix von Leitner
|
||||
Feng Tu
|
||||
Florian Schoppmann
|
||||
Forrest Cahoon
|
||||
Francois Charlier
|
||||
Frank Hempel
|
||||
Frank Keeney
|
||||
Frank McGeough
|
||||
@@ -342,11 +357,13 @@ Gautam Kachroo
|
||||
Gautam Mani
|
||||
Gavrie Philipson
|
||||
Gaz Iqbal
|
||||
Geoff Beier
|
||||
Georg Horn
|
||||
Georg Huettenegger
|
||||
Georg Lippitsch
|
||||
Georg Wicherski
|
||||
Gerd v. Egidy
|
||||
Gergely Nagy
|
||||
Gerhard Herre
|
||||
Gerrit Bruchhäuser
|
||||
Ghennadi Procopciuc
|
||||
@@ -362,6 +379,8 @@ Giuseppe D'Ambrosio
|
||||
Glen Nakamura
|
||||
Glen Scott
|
||||
Gokhan Sengun
|
||||
Gordon Marler
|
||||
Gorilla Maguila
|
||||
Grant Erickson
|
||||
Greg Hewgill
|
||||
Greg Morse
|
||||
@@ -384,8 +403,10 @@ Hans-Jurgen May
|
||||
Hardeep Singh
|
||||
Harshal Pradhan
|
||||
Hauke Duden
|
||||
He Qin
|
||||
Heikki Korpela
|
||||
Heinrich Ko
|
||||
Heinrich Schaefer
|
||||
Hendrik Visage
|
||||
Henrik Storner
|
||||
Henry Ludemann
|
||||
@@ -422,6 +443,7 @@ James Bursa
|
||||
James Cheng
|
||||
James Clancy
|
||||
James Cone
|
||||
James Dury
|
||||
James Gallagher
|
||||
James Griffiths
|
||||
James Housley
|
||||
@@ -441,6 +463,7 @@ Jason Glasgow
|
||||
Jason Liu
|
||||
Jason McDonald
|
||||
Jason S. Priebe
|
||||
Javier Barroso
|
||||
Jay Austin
|
||||
Jayesh A Shah
|
||||
Jaz Fresh
|
||||
@@ -453,6 +476,7 @@ Jean-Noel Rouvignac
|
||||
Jean-Philippe Barrette-LaPierre
|
||||
Jeff Connelly
|
||||
Jeff Johnson
|
||||
Jeff King
|
||||
Jeff Lawson
|
||||
Jeff Phillips
|
||||
Jeff Pohlmeyer
|
||||
@@ -462,6 +486,7 @@ Jeremy Friesner
|
||||
Jeremy Huddleston
|
||||
Jerome Muffat-Meridol
|
||||
Jerome Vouillon
|
||||
Jerry Krinock
|
||||
Jerry Wu
|
||||
Jes Badwal
|
||||
Jesper Jensen
|
||||
@@ -486,6 +511,7 @@ Johannes Bauer
|
||||
John Bradshaw
|
||||
John Crow
|
||||
John Dennis
|
||||
John Dunn
|
||||
John E. Malmberg
|
||||
John Gardiner Myers
|
||||
John Janssen
|
||||
@@ -569,6 +595,7 @@ Krishnendu Majumdar
|
||||
Krister Johansen
|
||||
Kristian Gunstone
|
||||
Kristian Köhntopp
|
||||
Kyle L. Huff
|
||||
Kyle Sallee
|
||||
Lachlan O'Dea
|
||||
Larry Campbell
|
||||
@@ -611,6 +638,7 @@ Mandy Wu
|
||||
Manfred Schwarb
|
||||
Manuel Massing
|
||||
Marc Boucher
|
||||
Marc Deslauriers
|
||||
Marc Doughty
|
||||
Marc Hoersken
|
||||
Marc Kleine-Budde
|
||||
@@ -618,6 +646,7 @@ Marcel Raad
|
||||
Marcel Roelofs
|
||||
Marcelo Juchem
|
||||
Marcin Adamski
|
||||
Marcin Gryszkalis
|
||||
Marcin Konicki
|
||||
Marco G. Salvagno
|
||||
Marco Maggi
|
||||
@@ -672,6 +701,7 @@ Maxim Prohorov
|
||||
Maxime Larocque
|
||||
Mehmet Bozkurt
|
||||
Mekonikum
|
||||
Melissa Mears
|
||||
Mettgut Jamalla
|
||||
Michael Benedict
|
||||
Michael Calmer
|
||||
@@ -683,6 +713,7 @@ Michael Jahn
|
||||
Michael Jerris
|
||||
Michael Mealling
|
||||
Michael Mueller
|
||||
Michael Osipov
|
||||
Michael Smith
|
||||
Michael Stillwell
|
||||
Michael Wallner
|
||||
@@ -700,6 +731,7 @@ Mike Crowe
|
||||
Mike Dobbs
|
||||
Mike Giancola
|
||||
Mike Hommey
|
||||
Mike Mio
|
||||
Mike Power
|
||||
Mike Protts
|
||||
Mike Revi
|
||||
@@ -744,6 +776,7 @@ Olaf Flebbe
|
||||
Olaf Stueben
|
||||
Olaf Stüben
|
||||
Oliver Gondža
|
||||
Oliver Kuckertz
|
||||
Olivier Berger
|
||||
Oren Tirosh
|
||||
Ori Avtalion
|
||||
@@ -762,8 +795,10 @@ Patrick Scott
|
||||
Patrick Smith
|
||||
Patrik Thunstrom
|
||||
Pau Garcia i Quiles
|
||||
Paul Donohue
|
||||
Paul Harrington
|
||||
Paul Howarth
|
||||
Paul Marks
|
||||
Paul Marquis
|
||||
Paul Moore
|
||||
Paul Nolan
|
||||
@@ -792,6 +827,8 @@ Peter Todd
|
||||
Peter Verhas
|
||||
Peter Wullinger
|
||||
Peteris Krumins
|
||||
Petr Bahula
|
||||
Petr Pisar
|
||||
Phil Blundell
|
||||
Phil Karn
|
||||
Phil Lisiecki
|
||||
@@ -875,6 +912,7 @@ Roland Zimmermann
|
||||
Rolland Dudemaine
|
||||
Roman Koifman
|
||||
Roman Mamedov
|
||||
Romulo A. Ceccon
|
||||
Ron Zapp
|
||||
Rosimildo da Silva
|
||||
Roy Shan
|
||||
@@ -884,6 +922,7 @@ Rutger Hofman
|
||||
Ryan Chan
|
||||
Ryan Nelson
|
||||
Ryan Schmidt
|
||||
Rémy Léone
|
||||
S. Moonesamy
|
||||
Salvador Dávila
|
||||
Salvatore Sorrentino
|
||||
@@ -909,11 +948,13 @@ Sebastian Rasmussen
|
||||
Sebastien Willemijns
|
||||
Senthil Raja Velu
|
||||
Sergei Nikulov
|
||||
Sergey Tatarincev
|
||||
Sergio Ballestrero
|
||||
Seshubabu Pasam
|
||||
Sh Diao
|
||||
Sharad Gupta
|
||||
Shard
|
||||
Shawn Landden
|
||||
Shawn Poulson
|
||||
Shmulik Regev
|
||||
Siddhartha Prakash Jain
|
||||
@@ -997,6 +1038,7 @@ Tom Mueller
|
||||
Tom Regner
|
||||
Tom Wright
|
||||
Tom Zerucha
|
||||
Tomas Hoger
|
||||
Tomas Mlcoch
|
||||
Tomas Pospisek
|
||||
Tomas Szepe
|
||||
@@ -1014,7 +1056,9 @@ Traian Nicolescu
|
||||
Troels Walsted Hansen
|
||||
Troy Engel
|
||||
Tupone Alfredo
|
||||
Tyler Hall
|
||||
Ulf Härnhammar
|
||||
Ulf Samuelsson
|
||||
Ulrich Doehner
|
||||
Ulrich Zadow
|
||||
Venkat Akella
|
||||
@@ -1041,15 +1085,18 @@ Wesley Laxton
|
||||
Wesley Miaw
|
||||
Wez Furlong
|
||||
Wilfredo Sanchez
|
||||
Will Dietz
|
||||
Willem Sparreboom
|
||||
Wojciech Zwiefka
|
||||
Wouter Van Rooy
|
||||
Wu Yongzheng
|
||||
Xavier Bouchoux
|
||||
Yaakov Selkowitz
|
||||
Yamada Yasuharu
|
||||
Yang Tse
|
||||
Yarram Sunil
|
||||
Yehoshua Hershberg
|
||||
Yi Huang
|
||||
Yukihiro Kawada
|
||||
Yuriy Sosov
|
||||
Yves Arrouye
|
||||
|
||||
65
docs/TODO
65
docs/TODO
@@ -16,8 +16,7 @@
|
||||
1.3 struct lifreq
|
||||
1.4 signal-based resolver timeouts
|
||||
1.5 get rid of PATH_MAX
|
||||
1.6 Happy Eyeball dual stack connect
|
||||
1.7 Modified buffer size approach
|
||||
1.6 Modified buffer size approach
|
||||
|
||||
2. libcurl - multi interface
|
||||
2.1 More non-blocking
|
||||
@@ -39,6 +38,7 @@
|
||||
5.2 support FF3 sqlite cookie files
|
||||
5.3 Rearrange request header order
|
||||
5.4 HTTP2/SPDY
|
||||
5.5 auth= in URLs
|
||||
|
||||
6. TELNET
|
||||
6.1 ditch stdin
|
||||
@@ -48,17 +48,14 @@
|
||||
|
||||
7. SMTP
|
||||
7.1 Pipelining
|
||||
7.2 Graceful base64 decoding failure
|
||||
7.3 Enhanced capability support
|
||||
7.2 Enhanced capability support
|
||||
|
||||
8. POP3
|
||||
8.1 Pipelining
|
||||
8.2 Graceful base64 decoding failure
|
||||
8.3 Enhanced capability support
|
||||
8.2 Enhanced capability support
|
||||
|
||||
9. IMAP
|
||||
9.1 Graceful base64 decoding failure
|
||||
9.2 Enhanced capability support
|
||||
9.1 Enhanced capability support
|
||||
|
||||
10. LDAP
|
||||
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
|
||||
its current API (as of libssh2 1.2.7) doesn't.
|
||||
|
||||
1.6 Happy Eyeball dual stack connect
|
||||
|
||||
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
|
||||
1.6 Modified buffer size approach
|
||||
|
||||
Current libcurl allocates a fixed 16K size buffer for download and an
|
||||
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
|
||||
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
|
||||
|
||||
@@ -331,14 +327,7 @@ to provide the data to send.
|
||||
|
||||
Add support for pipelining emails.
|
||||
|
||||
7.2 Graceful base64 decoding failure
|
||||
|
||||
Rather than shutting down the session and returning an error when the
|
||||
decoding of a base64 encoded authentication response fails, we should
|
||||
gracefully shutdown the authentication process by sending a * response to the
|
||||
server as per RFC4954.
|
||||
|
||||
7.3 Enhanced capability support
|
||||
7.2 Enhanced capability support
|
||||
|
||||
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||
capabilities returned from the EHLO command.
|
||||
@@ -349,28 +338,14 @@ to provide the data to send.
|
||||
|
||||
Add support for pipelining commands.
|
||||
|
||||
8.2 Graceful base64 decoding failure
|
||||
|
||||
Rather than shutting down the session and returning an error when the
|
||||
decoding of a base64 encoded authentication response fails, we should
|
||||
gracefully shutdown the authentication process by sending a * response to the
|
||||
server as per RFC5034.
|
||||
|
||||
8.3 Enhanced capability support
|
||||
8.2 Enhanced capability support
|
||||
|
||||
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||
capabilities returned from the CAPA command.
|
||||
|
||||
9. IMAP
|
||||
|
||||
9.1 Graceful base64 decoding failure
|
||||
|
||||
Rather than shutting down the session and returning an error when the
|
||||
decoding of a base64 encoded authentication response fails, we should
|
||||
gracefully shutdown the authentication process by sending a * response to the
|
||||
server as per RFC3501.
|
||||
|
||||
9.2 Enhanced capability support
|
||||
9.1 Enhanced capability support
|
||||
|
||||
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||
capabilities returned from the CAPABILITY command.
|
||||
|
||||
118
docs/curl.1
118
docs/curl.1
@@ -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
|
||||
contents but they should be encoded according to the URI standard.
|
||||
.IP "-G, --get"
|
||||
When used, this option will make all data specified with \fI-d, --data\fP or
|
||||
\fI--data-binary\fP to be used in an HTTP GET request instead of the POST
|
||||
request that otherwise would be used. The data will be appended to the URL
|
||||
with a '?' separator.
|
||||
When used, this option will make all data specified with \fI-d, --data\fP,
|
||||
\fI--data-binary\fP or \fI--data-urlencode\fP to be used in an HTTP GET
|
||||
request instead of the POST request that otherwise would be used. The data
|
||||
will be appended to the URL with a '?' separator.
|
||||
|
||||
If used in combination with -I, the POST data will instead be appended to the
|
||||
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
|
||||
server-specified Content-Disposition filename instead of extracting a filename
|
||||
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"
|
||||
(SSL) This option explicitly allows curl to perform "insecure" SSL connections
|
||||
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>"
|
||||
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
|
||||
used as if they were written on the actual command line. Options and their
|
||||
parameters must be specified on the same config file line, separated by
|
||||
whitespace, colon, the equals sign or any combination thereof (however,
|
||||
the preferred separator is the equals sign). 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.
|
||||
used as if they were written on the actual command line.
|
||||
|
||||
Options and their parameters must be specified on the same config file line,
|
||||
separated by whitespace, colon, or the equals sign. Long option names can
|
||||
optionally be given in the config file without the initial double dashes and
|
||||
if so, the colon or equals characters can be used as separators. If the option
|
||||
is specified with one or two dashes, there can be no colon or equals character
|
||||
between the option and its parameter.
|
||||
|
||||
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
|
||||
stdin.
|
||||
@@ -742,9 +750,6 @@ line. So, it could look similar to this:
|
||||
|
||||
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
|
||||
config file and uses it if found. The default config file is checked for in
|
||||
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.
|
||||
.IP "-l, --list-only"
|
||||
(FTP)
|
||||
When listing an FTP directory, this switch forces a name-only view.
|
||||
Especially useful if you want to machine-parse the contents of an FTP
|
||||
directory since the normal directory view doesn't use a standard look
|
||||
or format.
|
||||
When listing an FTP directory, this switch forces a name-only view. This is
|
||||
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 or
|
||||
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
|
||||
list only files in their response to NLST; they do not include
|
||||
subdirectories and symbolic links.
|
||||
Note: Some FTP servers list only files in their response to NLST; they do not
|
||||
include sub-directories 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"
|
||||
(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),
|
||||
@@ -894,10 +907,18 @@ return with exit code 63.
|
||||
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.
|
||||
.IP "--mail-rcpt <address>"
|
||||
(SMTP) Specify a single address that the given mail should get sent to. This
|
||||
option can be used multiple times to specify many recipients.
|
||||
(SMTP) Specify a single address, user name or mailing list name.
|
||||
|
||||
(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>"
|
||||
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
|
||||
@@ -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
|
||||
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.
|
||||
.IP "--oauth2-bearer"
|
||||
(IMAP/POP3/SMTP) Specify the Bearer Token for OAUTH 2.0 server authentication.
|
||||
The Bearer Token is used in conjuction with the user name which can be
|
||||
specified as part of the \fI--url\fP or \fI-u, --user\fP options.
|
||||
(IMAP, POP3, SMTP)
|
||||
Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
|
||||
is used in conjunction with the user name which can be specified as part of the
|
||||
\fI--url\fP or \fI-u, --user\fP options.
|
||||
|
||||
The Bearer Token and user name are formatted according to RFC 6750.
|
||||
|
||||
@@ -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
|
||||
specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP".
|
||||
(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>"
|
||||
Set password for use with the TLS authentication method specified with
|
||||
\fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set. (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 "--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"
|
||||
(HTTP) Request a compressed Transfer-Encoding response using one of the
|
||||
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
|
||||
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"
|
||||
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
|
||||
@@ -2055,6 +2101,8 @@ RTSP: mismatch of Session Identifiers
|
||||
unable to parse FTP file list
|
||||
.IP 88
|
||||
FTP chunk callback reported error
|
||||
.IP 89
|
||||
No connection available, the session will be queued
|
||||
.IP XX
|
||||
More error codes will appear here in future releases. The existing ones
|
||||
are meant to never change.
|
||||
|
||||
@@ -13,4 +13,4 @@ COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c \
|
||||
ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
|
||||
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
|
||||
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
|
||||
multi-uv.c xmlstream.c usercertinmem.c
|
||||
multi-uv.c xmlstream.c usercertinmem.c sessioninfo.c
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
/*
|
||||
@@ -59,7 +57,6 @@ int main(int argc, char **argv)
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
FILE * hd_src ;
|
||||
int hd ;
|
||||
struct stat file_info;
|
||||
|
||||
char *file;
|
||||
@@ -72,9 +69,7 @@ int main(int argc, char **argv)
|
||||
url = argv[2];
|
||||
|
||||
/* get the file size of the local file */
|
||||
hd = open(file, O_RDONLY) ;
|
||||
fstat(hd, &file_info);
|
||||
close(hd) ;
|
||||
stat(file, &file_info);
|
||||
|
||||
/* get a FILE * of the same file, could also be made with
|
||||
fdopen() from the previous descriptor, but hey this is just
|
||||
|
||||
105
docs/examples/sessioninfo.c
Normal file
105
docs/examples/sessioninfo.c
Normal 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;
|
||||
}
|
||||
@@ -22,8 +22,9 @@
|
||||
/* Example using an in memory PEM user certificate and RSA key to retrieve an
|
||||
* https page.
|
||||
* Written by Ishan SinghLevett, based on Theo Borm's cacertinmem.c.
|
||||
* Note this example does not use a CA certificate, however one should be used
|
||||
* if you want a properly secure connection
|
||||
* Note that to maintain simplicity this example does not use a CA certificate
|
||||
* 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>
|
||||
@@ -152,6 +153,18 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
|
||||
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 */
|
||||
return CURLE_OK ;
|
||||
|
||||
@@ -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_easy_send.pdf curl_multi_socket_action.pdf curl_multi_wait.pdf
|
||||
|
||||
m4macrodir = $(datadir)/aclocal
|
||||
dist_m4macro_DATA = libcurl.m4
|
||||
|
||||
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
|
||||
MAN2HTML= roffit --mandir=. < $< >$@
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@@ -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
|
||||
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
|
||||
option is only available in libcurl built with OpenSSL support. (Added in
|
||||
7.19.1)
|
||||
option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
.IP CURLOPT_USERPWD
|
||||
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
|
||||
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
|
||||
to prevent accidental information leakage.
|
||||
|
||||
At present only IMAP, POP3 and SMTP support login options as part of the
|
||||
details string. For more information about the login options please see
|
||||
RFC2384, RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
|
||||
|
||||
Use \fICURLOPT_HTTPAUTH\fP to specify the authentication method for HTTP based
|
||||
connections.
|
||||
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
|
||||
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.
|
||||
.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)
|
||||
CURLOPT_USERPWD option.
|
||||
|
||||
In order to specify the password to be used in conjunction with the user name
|
||||
use the \fICURLOPT_PASSWORD\fP option. (Added in 7.19.1)
|
||||
To specify the password and login options, along with the user name, use the
|
||||
\fICURLOPT_PASSWORD\fP and \fICURLOPT_LOGIN_OPTIONS\fP options. (Added in
|
||||
7.19.1)
|
||||
.IP CURLOPT_PASSWORD
|
||||
Pass a char * as parameter, which should be pointing to the zero terminated
|
||||
password to use for the transfer.
|
||||
|
||||
The CURLOPT_PASSWORD option should be used in conjunction with
|
||||
the \fICURLOPT_USERNAME\fP option. (Added in 7.19.1)
|
||||
The CURLOPT_PASSWORD option should be used in conjunction with the
|
||||
\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
|
||||
Pass a char * as parameter, which should be pointing to the zero terminated
|
||||
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
|
||||
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 (<>),
|
||||
however, should you not use an angled bracket as the first character libcurl
|
||||
will assume you provided a single email address and enclose that address
|
||||
within brackets for you.
|
||||
When performing a mail transfer, each recipient should be specified within a
|
||||
pair of angled brackets (<>), however, should you not use an angled bracket as
|
||||
the first character libcurl will assume you provided a single email address and
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
you want the transfer to start from. (Added in 7.11.0)
|
||||
.IP CURLOPT_CUSTOMREQUEST
|
||||
Pass a pointer to a zero terminated string as parameter. It can be used to
|
||||
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.
|
||||
Pass a pointer to a zero terminated string as parameter.
|
||||
|
||||
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
|
||||
to the particular request method, it will only change the actual string sent
|
||||
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:
|
||||
|
||||
With the HTTP protocol when you tell libcurl to do a HEAD request, but then
|
||||
specify a GET though a custom request libcurl will still act as if it sent a
|
||||
HEAD. To switch to a proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a
|
||||
proper POST use \fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch
|
||||
to a proper GET use CURLOPT_HTTPGET.
|
||||
When you tell libcurl to do a HEAD request, but then specify a GET though a
|
||||
custom request libcurl will still act as if it sent a HEAD. To switch to a
|
||||
proper HEAD use \fICURLOPT_NOBODY\fP, to switch to a proper POST use
|
||||
\fICURLOPT_POST\fP or \fICURLOPT_POSTFIELDS\fP and to switch to a proper GET
|
||||
use CURLOPT_HTTPGET.
|
||||
|
||||
With the POP3 protocol 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.
|
||||
|
||||
Restore to the internal default by setting this to NULL.
|
||||
Please don't perform this at will, on HTTP based requests, by making sure
|
||||
your server supports the command you are sending first.
|
||||
|
||||
Many people have wrongly used this option to replace the entire request with
|
||||
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
|
||||
\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
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
the format of your certificate. Supported formats are "PEM" and "DER", except
|
||||
with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
|
||||
(on iOS 5 or later, or OS X 10.6 or later) also support "P12" for
|
||||
(on iOS 5 or later, or OS X 10.7 or later) also support "P12" for
|
||||
PKCS#12-encoded files. (Added in 7.9.3)
|
||||
.IP CURLOPT_SSLKEY
|
||||
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.
|
||||
.IP CURLOPT_SSLVERSION
|
||||
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:
|
||||
.RS
|
||||
.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
|
||||
by default with 7.18.1).
|
||||
.IP CURL_SSLVERSION_TLSv1
|
||||
Force TLSv1
|
||||
Force TLSv1.x
|
||||
.IP CURL_SSLVERSION_SSLv2
|
||||
Force SSLv2
|
||||
.IP CURL_SSLVERSION_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
|
||||
.IP CURLOPT_SSL_VERIFYPEER
|
||||
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
|
||||
URL to which you told Curl to connect.
|
||||
|
||||
When the value is 1, libcurl will return a failure. It was previously (in
|
||||
7.28.0 and earlier) a debug option of some sorts, but it is no longer
|
||||
supported due to frequently leading to programmer mistakes.
|
||||
When the value is 1, \fIcurl_easy_setopt\fP will return an error and the option
|
||||
value will not be changed. It was previously (in 7.28.0 and earlier) a debug
|
||||
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
|
||||
certificate.
|
||||
@@ -2534,14 +2591,14 @@ The default value for this option is 2.
|
||||
This option controls checking the server's certificate's claimed identity.
|
||||
The server could be lying. To control lying, see
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP. If libcurl is built against NSS and
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP
|
||||
is ignored.
|
||||
|
||||
\fICURLOPT_SSL_VERIFYPEER\fP is zero, \fICURLOPT_SSL_VERIFYHOST\fP is also set
|
||||
to zero and cannot be overridden.
|
||||
.IP CURLOPT_CERTINFO
|
||||
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
|
||||
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
|
||||
7.19.1)
|
||||
.IP CURLOPT_RANDOM_FILE
|
||||
|
||||
@@ -250,6 +250,7 @@ CURLINFO_SSL_VERIFYRESULT 7.5
|
||||
CURLINFO_STARTTRANSFER_TIME 7.9.2
|
||||
CURLINFO_STRING 7.4.1
|
||||
CURLINFO_TEXT 7.9.6
|
||||
CURLINFO_TLS_SESSION 7.34.0
|
||||
CURLINFO_TOTAL_TIME 7.4.1
|
||||
CURLINFO_TYPEMASK 7.4.1
|
||||
CURLIOCMD_NOP 7.12.3
|
||||
@@ -394,6 +395,7 @@ CURLOPT_KRB4LEVEL 7.3 7.17.0
|
||||
CURLOPT_KRBLEVEL 7.16.4
|
||||
CURLOPT_LOCALPORT 7.15.2
|
||||
CURLOPT_LOCALPORTRANGE 7.15.2
|
||||
CURLOPT_LOGIN_OPTIONS 7.34.0
|
||||
CURLOPT_LOW_SPEED_LIMIT 7.1
|
||||
CURLOPT_LOW_SPEED_TIME 7.1
|
||||
CURLOPT_MAIL_AUTH 7.25.0
|
||||
@@ -593,6 +595,16 @@ CURLSSH_AUTH_KEYBOARD 7.16.1
|
||||
CURLSSH_AUTH_NONE 7.16.1
|
||||
CURLSSH_AUTH_PASSWORD 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
|
||||
CURLUSESSL_ALL 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_SSLv3 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_IFUNMODSINCE 7.9.7
|
||||
CURL_TIMECOND_LASTMOD 7.9.7
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
require it! */
|
||||
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
|
||||
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
|
||||
defined(ANDROID) || defined(__ANDROID__) || \
|
||||
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
|
||||
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
@@ -827,10 +827,10 @@ typedef enum {
|
||||
/* Name of proxy to use. */
|
||||
CINIT(PROXY, OBJECTPOINT, 4),
|
||||
|
||||
/* "name:password" to use when fetching. */
|
||||
/* "user:password;options" to use when fetching. */
|
||||
CINIT(USERPWD, OBJECTPOINT, 5),
|
||||
|
||||
/* "name:password" to use with proxy. */
|
||||
/* "user:password" to use with proxy. */
|
||||
CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
|
||||
|
||||
/* Range to get, specified as an ASCII string. */
|
||||
@@ -1388,8 +1388,7 @@ typedef enum {
|
||||
CINIT(ADDRESS_SCOPE, LONG, 171),
|
||||
|
||||
/* Collect certificate chain info and allow it to get retrievable with
|
||||
CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only
|
||||
working with OpenSSL-powered builds. */
|
||||
CURLINFO_CERTINFO after the transfer is complete. */
|
||||
CINIT(CERTINFO, LONG, 172),
|
||||
|
||||
/* "name" and "pwd" to use when fetching. */
|
||||
@@ -1569,6 +1568,9 @@ typedef enum {
|
||||
* Only supported by the c-ares DNS backend */
|
||||
CINIT(DNS_LOCAL_IP6, OBJECTPOINT, 223),
|
||||
|
||||
/* Set authentication options directly */
|
||||
CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
@@ -1659,9 +1661,12 @@ enum CURL_NETRC_OPTION {
|
||||
|
||||
enum {
|
||||
CURL_SSLVERSION_DEFAULT,
|
||||
CURL_SSLVERSION_TLSv1,
|
||||
CURL_SSLVERSION_TLSv1, /* TLS 1.x */
|
||||
CURL_SSLVERSION_SSLv2,
|
||||
CURL_SSLVERSION_SSLv3,
|
||||
CURL_SSLVERSION_TLSv1_0,
|
||||
CURL_SSLVERSION_TLSv1_1,
|
||||
CURL_SSLVERSION_TLSv1_2,
|
||||
|
||||
CURL_SSLVERSION_LAST /* never use, keep last */
|
||||
};
|
||||
@@ -1980,6 +1985,28 @@ struct curl_certinfo {
|
||||
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_LONG 0x200000
|
||||
#define CURLINFO_DOUBLE 0x300000
|
||||
@@ -2031,9 +2058,10 @@ typedef enum {
|
||||
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
|
||||
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
|
||||
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
|
||||
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
|
||||
/* Fill in new entries below here! */
|
||||
|
||||
CURLINFO_LASTONE = 42
|
||||
CURLINFO_LASTONE = 43
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
|
||||
@@ -110,71 +111,87 @@
|
||||
/* 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 */
|
||||
/* 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
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* 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
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* 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
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#cmakedefine CURL_SIZEOF_LONG ${CURL_SIZEOF_LONG}
|
||||
|
||||
/* Integral data type used for curl_socklen_t. */
|
||||
#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
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file sys/socket.h must be included by the external interface. */
|
||||
#cmakedefine CURL_PULL_SYS_SOCKET_H
|
||||
#ifdef CURL_PULL_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#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. */
|
||||
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. */
|
||||
#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. */
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
|
||||
/* 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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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. */
|
||||
#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 */
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
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
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 33
|
||||
#define LIBCURL_VERSION_MINOR 34
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
@@ -53,7 +53,7 @@
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x072100
|
||||
#define LIBCURL_VERSION_NUM 0x072200
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -269,6 +269,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
(option) == CURLOPT_DNS_INTERFACE || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP4 || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP6 || \
|
||||
(option) == CURLOPT_LOGIN_OPTIONS || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
|
||||
@@ -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_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 \
|
||||
http2.h
|
||||
http2.h sigpipe.h
|
||||
|
||||
@@ -645,10 +645,10 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
|
||||
const char *local_ip4)
|
||||
{
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
uint32_t a4;
|
||||
struct in_addr a4;
|
||||
|
||||
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 {
|
||||
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;
|
||||
#else /* c-ares version too old! */
|
||||
|
||||
@@ -164,7 +164,8 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
91
lib/base64.c
91
lib/base64.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -40,29 +40,45 @@
|
||||
static const char table64[]=
|
||||
"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;
|
||||
unsigned long i, v, x = 0;
|
||||
|
||||
for(i = 0, s = src; i < 4; i++, s++) {
|
||||
v = 0;
|
||||
|
||||
if(*s == '=') {
|
||||
x = (x << 6);
|
||||
padding++;
|
||||
}
|
||||
else {
|
||||
p = table64;
|
||||
|
||||
while(*p && (*p != *s)) {
|
||||
v++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if(*p == *s)
|
||||
x = (x << 6) + v;
|
||||
else if(*s == '=')
|
||||
x = (x << 6);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(padding < 1)
|
||||
dest[2] = curlx_ultouc(x & 0xFFUL);
|
||||
|
||||
x >>= 8;
|
||||
if(padding < 2)
|
||||
dest[1] = curlx_ultouc(x & 0xFFUL);
|
||||
|
||||
x >>= 8;
|
||||
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,
|
||||
unsigned char **outptr, size_t *outlen)
|
||||
{
|
||||
size_t srclen = 0;
|
||||
size_t length = 0;
|
||||
size_t equalsTerm = 0;
|
||||
size_t padding = 0;
|
||||
size_t i;
|
||||
size_t result;
|
||||
size_t numQuantums;
|
||||
unsigned char lastQuantum[3];
|
||||
size_t rawlen = 0;
|
||||
unsigned char *pos;
|
||||
unsigned char *newstr;
|
||||
|
||||
*outptr = NULL;
|
||||
*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])
|
||||
length++;
|
||||
|
||||
/* A maximum of two = padding characters is allowed */
|
||||
if(src[length] == '=') {
|
||||
equalsTerm++;
|
||||
if(src[length+equalsTerm] == '=')
|
||||
equalsTerm++;
|
||||
padding++;
|
||||
if(src[length + 1] == '=')
|
||||
padding++;
|
||||
}
|
||||
numQuantums = (length + equalsTerm) / 4;
|
||||
|
||||
/* Don't allocate a buffer if the decoded length is 0 */
|
||||
if(numQuantums == 0)
|
||||
return CURLE_OK;
|
||||
/* Check the = padding characters weren't part way through the input */
|
||||
if(length + padding != srclen)
|
||||
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
|
||||
(which may be partially thrown out) and the zero terminator. */
|
||||
newstr = malloc(rawlen+4);
|
||||
/* Calculate the size of the decoded string */
|
||||
rawlen = (numQuantums * 3) - padding;
|
||||
|
||||
/* Allocate our buffer including room for a zero terminator */
|
||||
newstr = malloc(rawlen + 1);
|
||||
if(!newstr)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
*outptr = newstr;
|
||||
pos = newstr;
|
||||
|
||||
/* Decode all but the last quantum (which may not decode to a
|
||||
multiple of 3 bytes) */
|
||||
for(i = 0; i < numQuantums - 1; i++) {
|
||||
decodeQuantum(newstr, src);
|
||||
newstr += 3; src += 4;
|
||||
/* Decode the quantums */
|
||||
for(i = 0; i < numQuantums; i++) {
|
||||
result = decodeQuantum(pos, src);
|
||||
if(!result) {
|
||||
Curl_safefree(newstr);
|
||||
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* This final decode may actually read slightly past the end of the buffer
|
||||
if the input string is missing pad bytes. This will almost always be
|
||||
harmless. */
|
||||
decodeQuantum(lastQuantum, src);
|
||||
for(i = 0; i < 3 - equalsTerm; i++)
|
||||
newstr[i] = lastQuantum[i];
|
||||
pos += result;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
newstr[i] = '\0'; /* zero terminate */
|
||||
/* Zero terminate */
|
||||
*pos = '\0';
|
||||
|
||||
*outlen = rawlen; /* return size of decoded data */
|
||||
/* Return the decoded data */
|
||||
*outptr = newstr;
|
||||
*outlen = rawlen;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -529,10 +529,10 @@
|
||||
#define SEND_TYPE_RETV int
|
||||
|
||||
/* Define to use the QsoSSL package. */
|
||||
#define USE_QSOSSL
|
||||
#undef USE_QSOSSL
|
||||
|
||||
/* Define to use the GSKit package. */
|
||||
#undef USE_GSKIT
|
||||
#define USE_GSKIT
|
||||
|
||||
/* Use the system keyring as the default CA bundle. */
|
||||
#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
|
||||
|
||||
310
lib/connect.c
310
lib/connect.c
@@ -164,8 +164,7 @@ tcpkeepalive(struct SessionHandle *data,
|
||||
static CURLcode
|
||||
singleipconnect(struct connectdata *conn,
|
||||
const Curl_addrinfo *ai, /* start connecting to this */
|
||||
curl_socket_t *sock,
|
||||
bool *connected);
|
||||
curl_socket_t *sock);
|
||||
|
||||
/*
|
||||
* Curl_timeleft() returns the amount of milliseconds left allowed for the
|
||||
@@ -233,45 +232,6 @@ long Curl_timeleft(struct SessionHandle *data,
|
||||
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,
|
||||
curl_socket_t sockfd, int af)
|
||||
{
|
||||
@@ -573,42 +533,53 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||
more address exists or error */
|
||||
static CURLcode trynextip(struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
int tempindex)
|
||||
{
|
||||
curl_socket_t sockfd;
|
||||
Curl_addrinfo *ai;
|
||||
CURLcode rc = CURLE_COULDNT_CONNECT;
|
||||
|
||||
/* First clean up after the failed socket.
|
||||
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
|
||||
interface is used with certain select() replacements such as kqueue. */
|
||||
curl_socket_t fd_to_close = conn->sock[sockindex];
|
||||
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||
*connected = FALSE;
|
||||
curl_socket_t fd_to_close = conn->tempsock[tempindex];
|
||||
conn->tempsock[tempindex] = CURL_SOCKET_BAD;
|
||||
|
||||
if(sockindex != FIRSTSOCKET) {
|
||||
Curl_closesocket(conn, fd_to_close);
|
||||
return CURLE_COULDNT_CONNECT; /* no next */
|
||||
if(sockindex == FIRSTSOCKET) {
|
||||
Curl_addrinfo *ai;
|
||||
int family;
|
||||
|
||||
if(conn->tempaddr[tempindex]) {
|
||||
/* find next address in the same protocol family */
|
||||
family = conn->tempaddr[tempindex]->ai_family;
|
||||
ai = conn->tempaddr[tempindex]->ai_next;
|
||||
}
|
||||
else {
|
||||
/* happy eyeballs - try the other protocol family */
|
||||
int firstfamily = conn->tempaddr[0]->ai_family;
|
||||
family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
|
||||
ai = conn->tempaddr[0]->ai_next;
|
||||
}
|
||||
|
||||
/* try the next address */
|
||||
ai = conn->ip_addr->ai_next;
|
||||
|
||||
while(ai) {
|
||||
CURLcode res = singleipconnect(conn, ai, &sockfd, connected);
|
||||
if(res)
|
||||
return res;
|
||||
if(sockfd != CURL_SOCKET_BAD) {
|
||||
/* store the new socket descriptor */
|
||||
conn->sock[sockindex] = sockfd;
|
||||
conn->ip_addr = ai;
|
||||
Curl_closesocket(conn, fd_to_close);
|
||||
return CURLE_OK;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if(fd_to_close != CURL_SOCKET_BAD)
|
||||
Curl_closesocket(conn, fd_to_close);
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
return;
|
||||
}
|
||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||
|
||||
if(!getaddressinfo((struct sockaddr*)&ssloc,
|
||||
conn->local_ip, &conn->local_port)) {
|
||||
@@ -732,11 +704,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
{
|
||||
struct SessionHandle *data = conn->data;
|
||||
CURLcode code = CURLE_OK;
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
long allow = DEFAULT_CONNECT_TIMEOUT;
|
||||
long allow;
|
||||
int error = 0;
|
||||
struct timeval now;
|
||||
enum chkconn_t chk;
|
||||
int result;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
|
||||
|
||||
@@ -759,25 +731,51 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
for(i=0; i<2; i++) {
|
||||
if(conn->tempsock[i] == CURL_SOCKET_BAD)
|
||||
continue;
|
||||
|
||||
#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(conn->tempsock[i], NULL);
|
||||
#endif
|
||||
|
||||
/* check socket for connect */
|
||||
chk = checkconnect(sockfd);
|
||||
if(CHKCONN_IDLE == chk) {
|
||||
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);
|
||||
goto next;
|
||||
error = ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* not an error, but also no connection yet */
|
||||
return code;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if(CHKCONN_CONNECTED == chk) {
|
||||
if(verifyconnect(sockfd, &error)) {
|
||||
}
|
||||
else if(result == CURL_CSELECT_OUT) {
|
||||
if(verifyconnect(conn->tempsock[i], &error)) {
|
||||
/* we are connected with TCP, awesome! */
|
||||
int other = i ^ 1;
|
||||
|
||||
/* use this socket from now on */
|
||||
conn->sock[sockindex] = conn->tempsock[i];
|
||||
conn->ip_addr = conn->tempaddr[i];
|
||||
conn->tempsock[i] = CURL_SOCKET_BAD;
|
||||
|
||||
/* close the other socket, if open */
|
||||
if(conn->tempsock[other] != CURL_SOCKET_BAD) {
|
||||
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 */
|
||||
code = Curl_connected_proxy(conn);
|
||||
code = Curl_connected_proxy(conn, sockindex);
|
||||
if(code)
|
||||
return code;
|
||||
|
||||
@@ -786,42 +784,51 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
*connected = TRUE;
|
||||
if(sockindex == FIRSTSOCKET)
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||
Curl_updateconninfo(conn, conn->sock[sockindex]);
|
||||
Curl_verboseconnect(conn);
|
||||
Curl_updateconninfo(conn, sockfd);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
/* nope, not connected for real */
|
||||
}
|
||||
else {
|
||||
/* nope, not connected */
|
||||
if(CHKCONN_FDSET_ERROR == chk) {
|
||||
(void)verifyconnect(sockfd, &error);
|
||||
infof(data, "%s\n",Curl_strerror(conn, error));
|
||||
}
|
||||
else
|
||||
infof(data, "Connection failed\n");
|
||||
}
|
||||
else if(result & CURL_CSELECT_ERR)
|
||||
(void)verifyconnect(conn->tempsock[i], &error);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
char ipaddress[MAX_IPADR_LEN];
|
||||
data->state.os_errno = error;
|
||||
SET_SOCKERRNO(error);
|
||||
}
|
||||
next:
|
||||
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->ip_addr->ai_next == NULL ?
|
||||
conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
|
||||
allow : allow / 2;
|
||||
code = trynextip(conn, sockindex, connected);
|
||||
|
||||
code = trynextip(conn, sockindex, i);
|
||||
}
|
||||
}
|
||||
|
||||
if(code) {
|
||||
error = SOCKERRNO;
|
||||
data->state.os_errno = error;
|
||||
failf(data, "Failed connect to %s:%ld; %s",
|
||||
conn->host.name, conn->port, Curl_strerror(conn, error));
|
||||
/* no more addresses to try */
|
||||
|
||||
/* if the first address family runs out of addresses to try before
|
||||
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;
|
||||
@@ -938,8 +945,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
|
||||
static CURLcode
|
||||
singleipconnect(struct connectdata *conn,
|
||||
const Curl_addrinfo *ai,
|
||||
curl_socket_t *sockp,
|
||||
bool *connected)
|
||||
curl_socket_t *sockp)
|
||||
{
|
||||
struct Curl_sockaddr_ex addr;
|
||||
int rc;
|
||||
@@ -948,9 +954,10 @@ singleipconnect(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
curl_socket_t sockfd;
|
||||
CURLcode res = CURLE_OK;
|
||||
char ipaddress[MAX_IPADR_LEN];
|
||||
long port;
|
||||
|
||||
*sockp = CURL_SOCKET_BAD;
|
||||
*connected = FALSE; /* default is not connected */
|
||||
|
||||
res = Curl_socket(conn, ai, &addr, &sockfd);
|
||||
if(res)
|
||||
@@ -961,7 +968,7 @@ singleipconnect(struct connectdata *conn,
|
||||
|
||||
/* store remote address and port used in this connection attempt */
|
||||
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 */
|
||||
error = ERRNO;
|
||||
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
||||
@@ -969,10 +976,7 @@ singleipconnect(struct connectdata *conn,
|
||||
Curl_closesocket(conn, sockfd);
|
||||
return CURLE_OK;
|
||||
}
|
||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||
infof(data, " Trying %s...\n", conn->ip_addr_str);
|
||||
|
||||
Curl_persistconninfo(conn);
|
||||
infof(data, " Trying %s...\n", ipaddress);
|
||||
|
||||
if(data->set.tcp_nodelay)
|
||||
tcpnodelay(conn, sockfd);
|
||||
@@ -1045,25 +1049,25 @@ singleipconnect(struct connectdata *conn,
|
||||
case EAGAIN:
|
||||
#endif
|
||||
#endif
|
||||
*sockp = sockfd;
|
||||
return CURLE_OK;
|
||||
res = CURLE_OK;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown error, fallthrough and try another address! */
|
||||
failf(data, "Failed to connect to %s: %s",
|
||||
conn->ip_addr_str, Curl_strerror(conn,error));
|
||||
infof(data, "Immediate connect fail for %s: %s\n",
|
||||
ipaddress, Curl_strerror(conn,error));
|
||||
data->state.os_errno = error;
|
||||
|
||||
/* connect failed */
|
||||
Curl_closesocket(conn, sockfd);
|
||||
res = CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(!res)
|
||||
*sockp = sockfd;
|
||||
|
||||
return CURLE_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1073,29 +1077,13 @@ singleipconnect(struct connectdata *conn,
|
||||
*/
|
||||
|
||||
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
const struct Curl_dns_entry *remotehost,
|
||||
curl_socket_t *sockconn, /* the connected socket */
|
||||
Curl_addrinfo **addr, /* the one we used */
|
||||
bool *connected) /* really connected? */
|
||||
const struct Curl_dns_entry *remotehost)
|
||||
{
|
||||
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();
|
||||
CURLcode res;
|
||||
|
||||
/*************************************************************
|
||||
* 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);
|
||||
long timeout_ms = Curl_timeleft(data, &before, TRUE);
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* a precaution, no need to continue if time already is up */
|
||||
@@ -1104,58 +1092,28 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
}
|
||||
|
||||
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
|
||||
* know for the given host. One by one until one IP succeeds.
|
||||
*/
|
||||
/* start connecting to first IP */
|
||||
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);
|
||||
|
||||
/*
|
||||
* Connecting with a Curl_addrinfo chain
|
||||
*/
|
||||
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)
|
||||
if(conn->tempsock[0] == CURL_SOCKET_BAD)
|
||||
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 */
|
||||
|
||||
return CURLE_OK;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -31,11 +31,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
bool *connected);
|
||||
|
||||
CURLcode Curl_connecthost(struct connectdata *conn,
|
||||
const struct Curl_dns_entry *host, /* connect to
|
||||
this */
|
||||
curl_socket_t *sockconn, /* not set if error */
|
||||
Curl_addrinfo **addr, /* the one we used */
|
||||
bool *connected); /* truly connected? */
|
||||
const struct Curl_dns_entry *host);
|
||||
|
||||
/* generic function that returns how much time there's left to run, according
|
||||
to the timeouts set */
|
||||
@@ -44,6 +40,8 @@ long Curl_timeleft(struct SessionHandle *data,
|
||||
bool duringconnect);
|
||||
|
||||
#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
|
||||
|
||||
@@ -834,7 +834,7 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
|
||||
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
|
||||
deprecation warnings, so let's not compile this unless it's necessary: */
|
||||
static OSStatus CopyIdentityWithLabelOldSchool(char *label,
|
||||
@@ -874,7 +874,7 @@ static OSStatus CopyIdentityWithLabelOldSchool(char *label,
|
||||
CFRelease(search);
|
||||
return status;
|
||||
}
|
||||
#endif /* CURL_SUPPORT_MAC_10_7 */
|
||||
#endif /* CURL_SUPPORT_MAC_10_6 */
|
||||
|
||||
static OSStatus CopyIdentityWithLabel(char *label,
|
||||
SecIdentityRef *out_cert_and_key)
|
||||
@@ -914,12 +914,12 @@ static OSStatus CopyIdentityWithLabel(char *label,
|
||||
CFRelease(query_dict);
|
||||
}
|
||||
else {
|
||||
#if CURL_SUPPORT_MAC_10_7
|
||||
#if CURL_SUPPORT_MAC_10_6
|
||||
/* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
|
||||
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||
#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
|
||||
to SecKeychainSearch. */
|
||||
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||
@@ -938,8 +938,10 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
|
||||
cPassword, kCFStringEncodingUTF8) : NULL;
|
||||
CFDataRef pkcs_data = NULL;
|
||||
|
||||
/* We can import P12 files on iOS or OS X 10.6 or later: */
|
||||
#if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
|
||||
/* We can import P12 files on iOS or OS X 10.7 or later: */
|
||||
/* These constants are documented as having first appeared in 10.6 but they
|
||||
raise linker errors when used on that cat for some reason. */
|
||||
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
|
||||
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
|
||||
NULL, NULL, &status)) {
|
||||
const void *cKeys[] = {kSecImportExportPassphrase};
|
||||
@@ -963,7 +965,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
|
||||
CFRelease(options);
|
||||
CFRelease(pkcs_data);
|
||||
}
|
||||
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
|
||||
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
|
||||
if(password)
|
||||
CFRelease(password);
|
||||
CFRelease(pkcs_url);
|
||||
@@ -1056,6 +1058,18 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
|
||||
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:
|
||||
(void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
|
||||
(void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
|
||||
@@ -1100,6 +1114,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
kTLSProtocol12,
|
||||
true);
|
||||
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:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol3,
|
||||
@@ -1130,10 +1159,17 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
true);
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
(void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kTLSProtocol1,
|
||||
true);
|
||||
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:
|
||||
err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
|
||||
kSSLProtocol2,
|
||||
@@ -1216,16 +1252,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
switch(err) {
|
||||
case errSecPkcs12VerifyFailure: case errSecAuthFailed:
|
||||
case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
|
||||
failf(data, "SSL: Incorrect password for the certificate \"%s\" "
|
||||
"and its private key.", data->set.str[STRING_CERT]);
|
||||
break;
|
||||
case errSecDecode: case errSecUnknownFormat:
|
||||
case errSecDecode: case -25257: /* errSecUnknownFormat */
|
||||
failf(data, "SSL: Couldn't make sense of the data in the "
|
||||
"certificate \"%s\" and its private key.",
|
||||
data->set.str[STRING_CERT]);
|
||||
break;
|
||||
case errSecPassphraseRequired:
|
||||
case -25260: /* errSecPassphraseRequired */
|
||||
failf(data, "SSL The certificate \"%s\" requires a password.",
|
||||
data->set.str[STRING_CERT]);
|
||||
break;
|
||||
@@ -1403,6 +1439,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
|
||||
/* We want to enable 1/n-1 when using a CBC cipher unless the user
|
||||
specifically doesn't want us doing that: */
|
||||
if(SSLSetSessionOption != NULL)
|
||||
SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
|
||||
!data->set.ssl_enable_beast);
|
||||
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
|
||||
|
||||
@@ -77,10 +77,6 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
|
||||
|
||||
ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
|
||||
|
||||
/* skip initial whitespaces */
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
if(checkprefix("NTLM", header)) {
|
||||
header += strlen("NTLM");
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
conn->response_header = NULL;
|
||||
break;
|
||||
case NTLMSTATE_TYPE2:
|
||||
input = aprintf("TT %s", conn->challenge_header);
|
||||
input = aprintf("TT %s\n", conn->challenge_header);
|
||||
if(!input)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
res = ntlm_wb_response(conn, input, ntlm->state);
|
||||
|
||||
258
lib/curl_sasl.c
258
lib/curl_sasl.c
@@ -23,6 +23,7 @@
|
||||
* RFC4422 Simple Authentication and Security Layer (SASL)
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC6749 OAuth 2.0 Authorization Framework
|
||||
* Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
@@ -40,6 +41,10 @@
|
||||
#include "warnless.h"
|
||||
#include "curl_memory.h"
|
||||
|
||||
#ifdef USE_NSS
|
||||
#include "nssg.h" /* for Curl_nss_force_init() */
|
||||
#endif
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
@@ -50,7 +55,7 @@
|
||||
/* 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
|
||||
*/
|
||||
static bool sasl_digest_get_key_value(const unsigned char *chlg,
|
||||
static bool sasl_digest_get_key_value(const char *chlg,
|
||||
const char *key,
|
||||
char *value,
|
||||
size_t max_val_len,
|
||||
@@ -59,7 +64,7 @@ static bool sasl_digest_get_key_value(const unsigned char *chlg,
|
||||
char *find_pos;
|
||||
size_t i;
|
||||
|
||||
find_pos = strstr((const char *) chlg, key);
|
||||
find_pos = strstr(chlg, key);
|
||||
if(!find_pos)
|
||||
return FALSE;
|
||||
|
||||
@@ -163,6 +168,36 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
#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()
|
||||
*
|
||||
@@ -172,7 +207,7 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* chlg64 [in] - Pointer to the base64 encoded challenge buffer.
|
||||
* chlg [in] - The challenge.
|
||||
* userp [in] - The user name.
|
||||
* passdwp [in] - The user's password.
|
||||
* 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.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *chlg,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t chlg64len = strlen(chlg64);
|
||||
unsigned char *chlg = (unsigned char *) NULL;
|
||||
size_t chlglen = 0;
|
||||
HMAC_context *ctxt;
|
||||
unsigned char digest[MD5_DIGEST_LEN];
|
||||
char *response;
|
||||
|
||||
/* Decode the challenge if necessary */
|
||||
if(chlg64len && *chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
if(chlg)
|
||||
chlglen = strlen(chlg);
|
||||
|
||||
/* Compute the digest using the password as the key */
|
||||
ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
|
||||
(const unsigned char *) passwdp,
|
||||
curlx_uztoui(strlen(passwdp)));
|
||||
|
||||
if(!ctxt) {
|
||||
Curl_safefree(chlg);
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Update the digest with the given challenge */
|
||||
if(chlglen > 0)
|
||||
Curl_HMAC_update(ctxt, chlg, curlx_uztoui(chlglen));
|
||||
|
||||
Curl_safefree(chlg);
|
||||
Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
|
||||
curlx_uztoui(chlglen));
|
||||
|
||||
/* Finalise the digest */
|
||||
Curl_HMAC_final(ctxt, digest);
|
||||
|
||||
/* Prepare the response */
|
||||
/* Generate the response */
|
||||
response = aprintf(
|
||||
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
userp, digest[0], digest[1], digest[2], digest[3], digest[4],
|
||||
@@ -231,13 +255,74 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
|
||||
Curl_safefree(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_decode_digest_md5_message()
|
||||
*
|
||||
* This is used to decode an already encoded DIGEST-MD5 challenge message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* chlg64 [in] - Pointer to the base64 encoded challenge message.
|
||||
* nonce [in/out] - The buffer where the nonce will be stored.
|
||||
* nlen [in] - The length of the nonce buffer.
|
||||
* realm [in/out] - The buffer where the realm will be stored.
|
||||
* rlen [in] - The length of the realm buffer.
|
||||
* alg [in/out] - The buffer where the algorithm will be stored.
|
||||
* alen [in] - The length of the algorithm buffer.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_sasl_decode_digest_md5_message(const char *chlg64,
|
||||
char *nonce, size_t nlen,
|
||||
char *realm, size_t rlen,
|
||||
char *alg, size_t alen)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned char *chlg = NULL;
|
||||
size_t chlglen = 0;
|
||||
size_t chlg64len = strlen(chlg64);
|
||||
|
||||
if(chlg64len && *chlg64 != '=') {
|
||||
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Ensure we have a valid challenge message */
|
||||
if(!chlg)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
|
||||
/* Retrieve nonce string from the challenge */
|
||||
if(!sasl_digest_get_key_value((char *)chlg, "nonce=\"", nonce, nlen, '\"')) {
|
||||
Curl_safefree(chlg);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Retrieve realm string from the challenge */
|
||||
if(!sasl_digest_get_key_value((char *)chlg, "realm=\"", realm, rlen, '\"')) {
|
||||
/* Challenge does not have a realm, set empty string [RFC2831] page 6 */
|
||||
strcpy(realm, "");
|
||||
}
|
||||
|
||||
/* Retrieve algorithm string from the challenge */
|
||||
if(!sasl_digest_get_key_value((char *)chlg, "algorithm=", alg, alen, ',')) {
|
||||
Curl_safefree(chlg);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
Curl_safefree(chlg);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_digest_md5_message()
|
||||
*
|
||||
@@ -247,10 +332,11 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
* Parameters:
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
* holding the result will be stored upon completion.
|
||||
* 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.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *nonce,
|
||||
const char *realm,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
#ifndef DEBUGBUILD
|
||||
static const char table16[] = "0123456789abcdef";
|
||||
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned char *chlg = (unsigned char *) NULL;
|
||||
size_t chlglen = 0;
|
||||
size_t i;
|
||||
MD5_context *ctxt;
|
||||
char *response = NULL;
|
||||
unsigned char digest[MD5_DIGEST_LEN];
|
||||
char HA1_hex[2 * MD5_DIGEST_LEN + 1];
|
||||
char HA2_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 cnonce[] = "12345678"; /* will be changed */
|
||||
char method[] = "AUTHENTICATE";
|
||||
char qop[] = "auth";
|
||||
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 */
|
||||
for(i = 0; i < 8; i++)
|
||||
cnonce[i] = table16[Curl_rand(data)%16];
|
||||
#endif
|
||||
|
||||
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
|
||||
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++)
|
||||
snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]);
|
||||
|
||||
snprintf(response, sizeof(response),
|
||||
"username=\"%s\",realm=\"%s\",nonce=\"%s\","
|
||||
/* Generate the response */
|
||||
response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\","
|
||||
"cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s",
|
||||
userp, realm, nonce,
|
||||
cnonce, nonceCount, uri, resp_hash_hex);
|
||||
if(!response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
/* Base64 encode the response */
|
||||
result = Curl_base64_encode(data, response, 0, outptr, outlen);
|
||||
|
||||
Curl_safefree(response);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -438,8 +495,36 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr,
|
||||
outlen);
|
||||
return Curl_ntlm_create_type1_message(userp, passwdp, ntlm, outptr, 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:
|
||||
*
|
||||
* 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.
|
||||
* passdwp [in] - The user's password.
|
||||
* 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.
|
||||
*/
|
||||
CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
|
||||
const char *header,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
char **outptr, size_t *outlen)
|
||||
{
|
||||
CURLcode result = Curl_ntlm_decode_type2_message(data, header, ntlm);
|
||||
|
||||
if(!result)
|
||||
result = Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm,
|
||||
outptr, outlen);
|
||||
|
||||
return result;
|
||||
return Curl_ntlm_create_type3_message(data, userp, passwdp, ntlm, outptr,
|
||||
outlen);
|
||||
}
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
/*
|
||||
* Curl_sasl_create_xoauth2_message()
|
||||
*
|
||||
* This is used to generate an already encoded XOAUTH2 message ready
|
||||
* for sending to the recipient.
|
||||
* This is used to generate an already encoded OAuth 2.0 message ready for
|
||||
* sending to the recipient.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - The session handle.
|
||||
* user [in] - The user name.
|
||||
* bearer [in] - The XOAUTH Bearer token.
|
||||
* bearer [in] - The bearer token.
|
||||
* outptr [in/out] - The address where a pointer to newly allocated memory
|
||||
* holding the result will be stored upon completion.
|
||||
* outlen [out] - The length of the output message.
|
||||
@@ -500,16 +578,20 @@ CURLcode Curl_sasl_create_xoauth2_message(struct SessionHandle *data,
|
||||
const char *bearer,
|
||||
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);
|
||||
|
||||
if(!xoauth)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Base64 encode the reply */
|
||||
return Curl_base64_encode(data, xoauth, strlen(xoauth), outptr,
|
||||
outlen);
|
||||
result = Curl_base64_encode(data, xoauth, strlen(xoauth), outptr, outlen);
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -66,16 +66,27 @@ CURLcode Curl_sasl_create_login_message(struct SessionHandle *data,
|
||||
size_t *outlen);
|
||||
|
||||
#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 */
|
||||
CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *chlg,
|
||||
const char *user,
|
||||
const char *passwdp,
|
||||
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 */
|
||||
CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
|
||||
const char *chlg64,
|
||||
const char *nonce,
|
||||
const char *realm,
|
||||
const char *user,
|
||||
const char *passwdp,
|
||||
const char *service,
|
||||
@@ -90,10 +101,13 @@ CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
|
||||
char **outptr,
|
||||
size_t *outlen);
|
||||
|
||||
/* This is used to decode an incoming NTLM type-2 message and generate a
|
||||
base64 encoded type-3 response */
|
||||
/* This is used to decode a base64 encoded NTLM type-2 message */
|
||||
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,
|
||||
const char *header,
|
||||
const char *userp,
|
||||
const char *passwdp,
|
||||
struct ntlmdata *ntlm,
|
||||
|
||||
@@ -180,6 +180,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
SP_PROT_TLS1_1_CLIENT |
|
||||
SP_PROT_TLS1_2_CLIENT;
|
||||
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:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
|
||||
break;
|
||||
|
||||
13
lib/cyassl.c
13
lib/cyassl.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -98,8 +98,19 @@ cyassl_connect_step1(struct connectdata *conn,
|
||||
req_method = SSLv23_client_method();
|
||||
break;
|
||||
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();
|
||||
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:
|
||||
req_method = SSLv3_client_method();
|
||||
break;
|
||||
|
||||
56
lib/easy.c
56
lib/easy.c
@@ -50,11 +50,6 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && defined(USE_OPENSSL)
|
||||
#define SIGPIPE_IGNORE 1
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "strequal.h"
|
||||
#include "urldata.h"
|
||||
#include <curl/curl.h>
|
||||
@@ -78,6 +73,7 @@
|
||||
#include "warnless.h"
|
||||
#include "conncache.h"
|
||||
#include "multiif.h"
|
||||
#include "sigpipe.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -85,56 +81,6 @@
|
||||
/* The last #include file should be: */
|
||||
#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
|
||||
of win32_init() */
|
||||
static void win32_cleanup(void)
|
||||
|
||||
188
lib/ftp.c
188
lib/ftp.c
@@ -1802,23 +1802,87 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
|
||||
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,
|
||||
int ftpcode)
|
||||
{
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
CURLcode result;
|
||||
struct SessionHandle *data=conn->data;
|
||||
Curl_addrinfo *conninfo;
|
||||
struct Curl_dns_entry *addr=NULL;
|
||||
int rc;
|
||||
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 */
|
||||
|
||||
if((ftpc->count1 == 0) &&
|
||||
@@ -1851,7 +1915,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||
}
|
||||
if(ptr) {
|
||||
newport = (unsigned short)(num & 0xffff);
|
||||
ftpc->newport = (unsigned short)(num & 0xffff);
|
||||
|
||||
if(conn->bits.tunnel_proxy ||
|
||||
conn->proxytype == CURLPROXY_SOCKS5 ||
|
||||
@@ -1860,10 +1924,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
conn->proxytype == CURLPROXY_SOCKS4A)
|
||||
/* proxy tunnel -> use other host info because ip_addr_str is the
|
||||
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
|
||||
/* 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
|
||||
@@ -1916,14 +1981,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
conn->proxytype == CURLPROXY_SOCKS4A)
|
||||
/* proxy tunnel -> use other host info because ip_addr_str is the
|
||||
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
|
||||
snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str);
|
||||
snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s",
|
||||
conn->ip_addr_str);
|
||||
}
|
||||
else
|
||||
snprintf(newhost, sizeof(newhost),
|
||||
snprintf(ftpc->newhost, sizeof(ftpc->newhost),
|
||||
"%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) {
|
||||
/* EPSV failed, move on to PASV */
|
||||
@@ -1957,24 +2023,21 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* normal, direct, ftp connection */
|
||||
rc = Curl_resolv(conn, newhost, newport, &addr);
|
||||
rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
|
||||
if(rc == CURLRESOLV_PENDING)
|
||||
/* BLOCKING */
|
||||
(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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
result = Curl_connecthost(conn,
|
||||
addr,
|
||||
&conn->sock[SECONDARYSOCKET],
|
||||
&conninfo,
|
||||
&connected);
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
|
||||
result = Curl_connecthost(conn, addr);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = connected;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* connect to connect and we should not be "hanging" here waiting.
|
||||
* connect to connect.
|
||||
*/
|
||||
|
||||
if(data->set.verbose)
|
||||
/* 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;
|
||||
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? */
|
||||
if(connected) {
|
||||
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 {
|
||||
if(result && (ftpc->count1 == 0)) {
|
||||
|
||||
@@ -147,6 +147,12 @@ struct ftp_conn {
|
||||
curl_off_t known_filesize; /* file size is different from -1, if wildcard
|
||||
LIST parsing was done and wc_statemach set
|
||||
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 */
|
||||
|
||||
@@ -277,7 +277,57 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
|
||||
ptr.to_certinfo = &data->info.certs;
|
||||
*param_slistp = ptr.to_slist;
|
||||
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:
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
|
||||
337
lib/gskit.c
337
lib/gskit.c
@@ -32,6 +32,35 @@
|
||||
#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
|
||||
#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
|
||||
# include <limits.h>
|
||||
#endif
|
||||
@@ -54,30 +83,65 @@
|
||||
#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. */
|
||||
typedef struct {
|
||||
const char *name; /* Cipher name. */
|
||||
const char *gsktoken; /* Corresponding token for GSKit String. */
|
||||
int sslver; /* SSL version. */
|
||||
unsigned int versions; /* SSL version flags. */
|
||||
} gskit_cipher;
|
||||
|
||||
static const gskit_cipher ciphertable[] = {
|
||||
{ "null-md5", "01", CURL_SSLVERSION_SSLv3 },
|
||||
{ "null-sha", "02", CURL_SSLVERSION_SSLv3 },
|
||||
{ "exp-rc4-md5", "03", CURL_SSLVERSION_SSLv3 },
|
||||
{ "rc4-md5", "04", CURL_SSLVERSION_SSLv3 },
|
||||
{ "rc4-sha", "05", CURL_SSLVERSION_SSLv3 },
|
||||
{ "exp-rc2-cbc-md5", "06", CURL_SSLVERSION_SSLv3 },
|
||||
{ "exp-des-cbc-sha", "09", CURL_SSLVERSION_SSLv3 },
|
||||
{ "des-cbc3-sha", "0A", CURL_SSLVERSION_SSLv3 },
|
||||
{ "aes128-sha", "2F", CURL_SSLVERSION_TLSv1 },
|
||||
{ "aes256-sha", "35", CURL_SSLVERSION_TLSv1 },
|
||||
{ "rc4-md5", "1", CURL_SSLVERSION_SSLv2 },
|
||||
{ "exp-rc4-md5", "2", CURL_SSLVERSION_SSLv2 },
|
||||
{ "rc2-md5", "3", CURL_SSLVERSION_SSLv2 },
|
||||
{ "exp-rc2-md5", "4", CURL_SSLVERSION_SSLv2 },
|
||||
{ "des-cbc-md5", "6", CURL_SSLVERSION_SSLv2 },
|
||||
{ "des-cbc3-md5", "7", CURL_SSLVERSION_SSLv2 },
|
||||
{ "null-md5", "01",
|
||||
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
|
||||
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
|
||||
{ "null-sha", "02",
|
||||
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
|
||||
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
|
||||
{ "exp-rc4-md5", "03",
|
||||
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
|
||||
{ "rc4-md5", "04",
|
||||
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
|
||||
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
|
||||
{ "rc4-sha", "05",
|
||||
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
|
||||
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
|
||||
{ "exp-rc2-cbc-md5", "06",
|
||||
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 }
|
||||
};
|
||||
|
||||
@@ -142,8 +206,8 @@ static CURLcode gskit_status(struct SessionHandle * data, int rc,
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_enum(struct SessionHandle * data,
|
||||
gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value)
|
||||
static CURLcode set_enum(struct SessionHandle *data, gsk_handle h,
|
||||
GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
|
||||
{
|
||||
int rc = gsk_attribute_set_enum(h, id, value);
|
||||
|
||||
@@ -153,6 +217,9 @@ static CURLcode set_enum(struct SessionHandle * data,
|
||||
case GSK_ERROR_IO:
|
||||
failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
|
||||
break;
|
||||
case GSK_ATTRIBUTE_INVALID_ID:
|
||||
if(unsupported_ok)
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
|
||||
break;
|
||||
@@ -161,8 +228,8 @@ static CURLcode set_enum(struct SessionHandle * data,
|
||||
}
|
||||
|
||||
|
||||
static CURLcode set_buffer(struct SessionHandle * data,
|
||||
gsk_handle h, GSK_BUF_ID id, const char * buffer)
|
||||
static CURLcode set_buffer(struct SessionHandle *data, gsk_handle h,
|
||||
GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
|
||||
{
|
||||
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:
|
||||
failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
|
||||
break;
|
||||
case GSK_ATTRIBUTE_INVALID_ID:
|
||||
if(unsupported_ok)
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
default:
|
||||
failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
|
||||
break;
|
||||
@@ -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];
|
||||
char * sslv2ciphers;
|
||||
char * sslv3ciphers;
|
||||
const char *clp;
|
||||
const gskit_cipher *ctp;
|
||||
char * v2p;
|
||||
char * v3p;
|
||||
int i;
|
||||
int l;
|
||||
bool unsupported;
|
||||
CURLcode cc;
|
||||
struct {
|
||||
char *buf;
|
||||
char *ptr;
|
||||
} ciphers[CURL_GSKPROTO_LAST];
|
||||
|
||||
/* 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
|
||||
GSKit tokens are always shorter than their cipher names, allocated buffers
|
||||
will always be large enough to accomodate the result. */
|
||||
i = strlen(cipherlist) + 1;
|
||||
v2p = malloc(i);
|
||||
if(!v2p)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
v3p = malloc(i);
|
||||
if(!v3p) {
|
||||
free(v2p);
|
||||
l = strlen(cipherlist) + 1;
|
||||
memset((char *) ciphers, 0, sizeof ciphers);
|
||||
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
|
||||
ciphers[i].buf = malloc(l);
|
||||
if(!ciphers[i].buf) {
|
||||
while(i--)
|
||||
free(ciphers[i].buf);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
sslv2ciphers = v2p;
|
||||
sslv3ciphers = v3p;
|
||||
ciphers[i].ptr = ciphers[i].buf;
|
||||
*ciphers[i].ptr = '\0';
|
||||
}
|
||||
|
||||
/* Process each cipher in input string. */
|
||||
unsupported = FALSE;
|
||||
cc = CURLE_OK;
|
||||
for(;;) {
|
||||
for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
|
||||
cipherlist++;
|
||||
i = cipherlist - clp;
|
||||
if(!i)
|
||||
l = cipherlist - clp;
|
||||
if(!l)
|
||||
break;
|
||||
/* Search the cipher in our table. */
|
||||
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;
|
||||
if(!ctp->name)
|
||||
failf(data, "Unknown cipher %.*s: ignored", i, clp);
|
||||
if(!ctp->name) {
|
||||
failf(data, "Unknown cipher %.*s", l, clp);
|
||||
cc = CURLE_SSL_CIPHER;
|
||||
}
|
||||
else {
|
||||
switch (ctp->sslver) {
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
strcpy(v2p, ctp->gsktoken);
|
||||
v2p += strlen(v2p);
|
||||
break;
|
||||
default:
|
||||
/* GSKit wants TLSv1 ciphers with SSLv3 ciphers. */
|
||||
strcpy(v3p, ctp->gsktoken);
|
||||
v3p += strlen(v3p);
|
||||
break;
|
||||
unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
|
||||
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
|
||||
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
|
||||
if(ctp->versions & (1 << i)) {
|
||||
strcpy(ciphers[i].ptr, ctp->gsktoken);
|
||||
ciphers[i].ptr += strlen(ctp->gsktoken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,13 +361,63 @@ static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h)
|
||||
while(is_separator(*cipherlist))
|
||||
cipherlist++;
|
||||
}
|
||||
*v2p = '\0';
|
||||
*v3p = '\0';
|
||||
cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS, sslv2ciphers);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS, sslv3ciphers);
|
||||
free(sslv2ciphers);
|
||||
free(sslv3ciphers);
|
||||
|
||||
/* Disable protocols with empty cipher lists. */
|
||||
for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
|
||||
if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
|
||||
*protoflags &= ~(1 << i);
|
||||
ciphers[i].buf[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -333,15 +458,15 @@ static CURLcode init_environment(struct SessionHandle * data,
|
||||
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)
|
||||
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)
|
||||
c = set_buffer(data, h, GSK_KEYRING_FILE, file);
|
||||
c = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
|
||||
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)
|
||||
c = set_buffer(data, h, GSK_KEYRING_PW, password);
|
||||
c = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
|
||||
|
||||
if(c == CURLE_OK) {
|
||||
/* Locate CAs, Client certificate and key according to our settings.
|
||||
@@ -438,10 +563,8 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
|
||||
char *keyringfile;
|
||||
char *keyringpwd;
|
||||
char *keyringlabel;
|
||||
char * v2ciphers;
|
||||
char * v3ciphers;
|
||||
char *sni;
|
||||
bool sslv2enable, sslv3enable, tlsv1enable;
|
||||
unsigned int protoflags;
|
||||
long timeout;
|
||||
Qso_OverlappedIO_t commarea;
|
||||
|
||||
@@ -491,43 +614,39 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
|
||||
return cc;
|
||||
|
||||
/* 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;
|
||||
switch (data->set.ssl.version) {
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
sslv2enable = true;
|
||||
protoflags = CURL_GSKPROTO_SSLV2_MASK;
|
||||
sni = (char *) NULL;
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
sslv3enable = true;
|
||||
protoflags = CURL_GSKPROTO_SSLV2_MASK;
|
||||
sni = (char *) NULL;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
tlsv1enable = true;
|
||||
protoflags = CURL_GSKPROTO_TLSV10_MASK |
|
||||
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
|
||||
break;
|
||||
default: /* CURL_SSLVERSION_DEFAULT. */
|
||||
sslv3enable = true;
|
||||
tlsv1enable = true;
|
||||
case CURL_SSLVERSION_TLSv1_0:
|
||||
protoflags = CURL_GSKPROTO_TLSV10_MASK;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_1:
|
||||
protoflags = CURL_GSKPROTO_TLSV11_MASK;
|
||||
break;
|
||||
case CURL_SSLVERSION_TLSv1_2:
|
||||
protoflags = CURL_GSKPROTO_TLSV12_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Process SNI. Ignore if not supported (on OS400 < V7R1). */
|
||||
if(sni) {
|
||||
rc = gsk_attribute_set_buffer(connssl->handle,
|
||||
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, 0);
|
||||
switch (rc) {
|
||||
case GSK_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;
|
||||
}
|
||||
cc = set_buffer(data, connssl->handle,
|
||||
GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
|
||||
if(cc == CURLE_UNSUPPORTED_PROTOCOL)
|
||||
cc = CURLE_OK;
|
||||
}
|
||||
|
||||
/* Set session parameters. */
|
||||
@@ -544,23 +663,51 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
|
||||
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)
|
||||
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
|
||||
sslv2enable? GSK_PROTOCOL_SSLV2_ON:
|
||||
GSK_PROTOCOL_SSLV2_OFF);
|
||||
(protoflags & CURL_GSKPROTO_SSLV2_MASK)?
|
||||
GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
|
||||
sslv3enable? GSK_PROTOCOL_SSLV3_ON:
|
||||
GSK_PROTOCOL_SSLV3_OFF);
|
||||
(protoflags & CURL_GSKPROTO_SSLV3_MASK)?
|
||||
GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
|
||||
if(cc == CURLE_OK)
|
||||
cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
|
||||
sslv3enable? GSK_PROTOCOL_TLSV1_ON:
|
||||
GSK_PROTOCOL_TLSV1_OFF);
|
||||
(protoflags & CURL_GSKPROTO_TLSV10_MASK)?
|
||||
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)
|
||||
cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
|
||||
data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
|
||||
GSK_SERVER_AUTH_PASSTHRU);
|
||||
GSK_SERVER_AUTH_PASSTHRU, FALSE);
|
||||
|
||||
if(cc == CURLE_OK) {
|
||||
/* Start handshake. Try asynchronous first. */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -633,10 +633,8 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
else
|
||||
infof(data, "\t server certificate verification OK\n");
|
||||
}
|
||||
else {
|
||||
else
|
||||
infof(data, "\t server certificate verification SKIPPED\n");
|
||||
goto after_server_cert_verification;
|
||||
}
|
||||
|
||||
/* initialize an X.509 certificate structure. */
|
||||
gnutls_x509_crt_init(&x509_cert);
|
||||
@@ -766,8 +764,6 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
|
||||
gnutls_x509_crt_deinit(x509_cert);
|
||||
|
||||
after_server_cert_verification:
|
||||
|
||||
/* compression algorithm (if any) */
|
||||
ptr = gnutls_compression_get_name(gnutls_compression_get(session));
|
||||
/* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#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 */
|
||||
|
||||
#include "hostcheck.h"
|
||||
@@ -94,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */
|
||||
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT or NSS */
|
||||
|
||||
13
lib/hostip.c
13
lib/hostip.c
@@ -291,9 +291,10 @@ remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
|
||||
{
|
||||
struct hostcache_prune_data user;
|
||||
|
||||
if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
|
||||
/* cache forever means never prune, and NULL hostcache means
|
||||
we can't do it */
|
||||
if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache ||
|
||||
dns->inuse)
|
||||
/* 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;
|
||||
|
||||
time(&user.now);
|
||||
@@ -428,9 +429,13 @@ int Curl_resolv(struct connectdata *conn,
|
||||
/* free the allocated entry_id again */
|
||||
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 */
|
||||
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 */
|
||||
}
|
||||
|
||||
if(dns) {
|
||||
dns->inuse++; /* we use it! */
|
||||
|
||||
93
lib/http.c
93
lib/http.c
@@ -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
|
||||
* 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 *end;
|
||||
char *value;
|
||||
size_t len;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(header);
|
||||
|
||||
/* Find the end of the header name */
|
||||
while(*h && (*h != ':'))
|
||||
++h;
|
||||
while(*header && (*header != ':'))
|
||||
++header;
|
||||
|
||||
if(*h)
|
||||
if(*header)
|
||||
/* Skip over colon */
|
||||
++h;
|
||||
++header;
|
||||
|
||||
/* Find the first non-space letter */
|
||||
start = h;
|
||||
start = header;
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
|
||||
@@ -699,9 +699,8 @@ Curl_http_output_auth(struct connectdata *conn,
|
||||
* proxy CONNECT loop.
|
||||
*/
|
||||
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
int httpcode,
|
||||
const char *header) /* the first non-space */
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
const char *auth) /* the first non-space */
|
||||
{
|
||||
/*
|
||||
* This resource requires authentication
|
||||
@@ -709,24 +708,17 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
unsigned long *availp;
|
||||
const char *start;
|
||||
struct auth *authp;
|
||||
|
||||
if(httpcode == 407) {
|
||||
start = header+strlen("Proxy-authenticate:");
|
||||
if(proxy) {
|
||||
availp = &data->info.proxyauthavail;
|
||||
authp = &data->state.authproxy;
|
||||
}
|
||||
else {
|
||||
start = header+strlen("WWW-Authenticate:");
|
||||
availp = &data->info.httpauthavail;
|
||||
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
|
||||
* 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
|
||||
if(checkprefix("GSS-Negotiate", start) ||
|
||||
checkprefix("Negotiate", start)) {
|
||||
if(checkprefix("GSS-Negotiate", auth) ||
|
||||
checkprefix("Negotiate", auth)) {
|
||||
int neg;
|
||||
*availp |= CURLAUTH_GSSNEGOTIATE;
|
||||
authp->avail |= CURLAUTH_GSSNEGOTIATE;
|
||||
@@ -760,7 +752,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
data->state.authproblem = TRUE;
|
||||
}
|
||||
else {
|
||||
neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
|
||||
neg = Curl_input_negotiate(conn, proxy, auth);
|
||||
if(neg == 0) {
|
||||
DEBUGASSERT(!data->req.newurl);
|
||||
data->req.newurl = strdup(data->change.url);
|
||||
@@ -779,14 +771,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
#endif
|
||||
#ifdef USE_NTLM
|
||||
/* NTLM support requires the SSL crypto libs */
|
||||
if(checkprefix("NTLM", start)) {
|
||||
if(checkprefix("NTLM", auth)) {
|
||||
*availp |= CURLAUTH_NTLM;
|
||||
authp->avail |= CURLAUTH_NTLM;
|
||||
if(authp->picked == CURLAUTH_NTLM ||
|
||||
authp->picked == CURLAUTH_NTLM_WB) {
|
||||
/* NTLM authentication is picked and activated */
|
||||
CURLcode ntlm =
|
||||
Curl_input_ntlm(conn, (httpcode == 407)?TRUE:FALSE, start);
|
||||
Curl_input_ntlm(conn, proxy, auth);
|
||||
if(CURLE_OK == ntlm) {
|
||||
data->state.authproblem = FALSE;
|
||||
#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
|
||||
* ntlm_auth for generating the type 3 message later */
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
if(checkprefix("NTLM", start)) {
|
||||
start += strlen("NTLM");
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
if(*start)
|
||||
if((conn->challenge_header = strdup(start)) == NULL)
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
if(checkprefix("NTLM", auth)) {
|
||||
auth += strlen("NTLM");
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
if(*auth)
|
||||
if((conn->challenge_header = strdup(auth)) == NULL)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -820,7 +812,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if(checkprefix("Digest", start)) {
|
||||
if(checkprefix("Digest", auth)) {
|
||||
if((authp->avail & CURLAUTH_DIGEST) != 0) {
|
||||
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
|
||||
* incoming data from this header in case we are gonna use
|
||||
* Digest. */
|
||||
dig = Curl_input_digest(conn, (httpcode == 407)?TRUE:FALSE, start);
|
||||
dig = Curl_input_digest(conn, proxy, auth);
|
||||
|
||||
if(CURLDIGEST_FINE != dig) {
|
||||
infof(data, "Authentication problem. Ignoring this.\n");
|
||||
@@ -843,7 +835,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(checkprefix("Basic", start)) {
|
||||
if(checkprefix("Basic", auth)) {
|
||||
*availp |= CURLAUTH_BASIC;
|
||||
authp->avail |= 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 */
|
||||
while(*start && *start != ',') /* read up to the next comma */
|
||||
start++;
|
||||
if(*start == ',') /* if we're on a comma, skip it */
|
||||
start++;
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
while(*auth && *auth != ',') /* read up to the next comma */
|
||||
auth++;
|
||||
if(*auth == ',') /* if we're on a comma, skip it */
|
||||
auth++;
|
||||
while(*auth && ISSPACE(*auth))
|
||||
auth++;
|
||||
}
|
||||
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
|
||||
redirected request is being out on thin ice. Except if the host name
|
||||
is the same as the first one! */
|
||||
char *cookiehost = copy_header_value(ptr);
|
||||
char *cookiehost = Curl_copy_header_value(ptr);
|
||||
if(!cookiehost)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
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 */
|
||||
else if(checkprefix("Content-Type:", k->p)) {
|
||||
char *contenttype = copy_header_value(k->p);
|
||||
char *contenttype = Curl_copy_header_value(k->p);
|
||||
if(!contenttype)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!*contenttype)
|
||||
@@ -3259,7 +3251,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
}
|
||||
}
|
||||
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 */
|
||||
if(conn->bundle && conn->bundle->server_supports_pipelining) {
|
||||
@@ -3455,7 +3447,16 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
(401 == k->httpcode)) ||
|
||||
(checkprefix("Proxy-authenticate:", k->p) &&
|
||||
(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)
|
||||
return result;
|
||||
}
|
||||
@@ -3463,7 +3464,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
checkprefix("Location:", k->p) &&
|
||||
!data->req.location) {
|
||||
/* 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)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!*location)
|
||||
|
||||
@@ -35,11 +35,12 @@ extern const struct Curl_handler Curl_handler_http;
|
||||
extern const struct Curl_handler Curl_handler_https;
|
||||
#endif
|
||||
|
||||
/* Header specific functions */
|
||||
bool Curl_compareheader(const char *headerline, /* line to check */
|
||||
const char *header, /* header keyword _with_ colon */
|
||||
const char *content); /* content string to find */
|
||||
|
||||
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 */
|
||||
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn,
|
||||
int httpcode, const char *header);
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
const char *auth);
|
||||
CURLcode Curl_http_auth_act(struct connectdata *conn);
|
||||
CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
|
||||
|
||||
|
||||
@@ -141,10 +141,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
|
||||
d = &data->state.digest;
|
||||
}
|
||||
|
||||
/* skip initial whitespaces */
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
if(checkprefix("Digest", header)) {
|
||||
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
|
||||
this sorted out, I must urge you dear friend to read up on the RFC2617
|
||||
section 3.2.2, */
|
||||
size_t urilen;
|
||||
unsigned char md5buf[16]; /* 16 bytes/128 bits */
|
||||
unsigned char request_digest[33];
|
||||
unsigned char *md5this;
|
||||
@@ -440,13 +437,13 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
Further details on Digest implementation differences:
|
||||
http://www.fngtps.com/2006/09/http-authentication
|
||||
*/
|
||||
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
|
||||
md5this = (unsigned char *)aprintf("%s:%.*s", request,
|
||||
curlx_sztosi(tmp - (char *)uripath),
|
||||
uripath);
|
||||
}
|
||||
|
||||
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL))
|
||||
urilen = tmp - (char *)uripath;
|
||||
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")) {
|
||||
/* 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\", "
|
||||
"realm=\"%s\", "
|
||||
"nonce=\"%s\", "
|
||||
"uri=\"%s\", "
|
||||
"uri=\"%.*s\", "
|
||||
"cnonce=\"%s\", "
|
||||
"nc=%08x, "
|
||||
"qop=%s, "
|
||||
@@ -520,7 +517,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
userp_quoted,
|
||||
d->realm,
|
||||
d->nonce,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
urilen, uripath, /* this is the PATH part of the URL */
|
||||
d->cnonce,
|
||||
d->nc,
|
||||
d->qop,
|
||||
@@ -537,13 +534,13 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
||||
"username=\"%s\", "
|
||||
"realm=\"%s\", "
|
||||
"nonce=\"%s\", "
|
||||
"uri=\"%s\", "
|
||||
"uri=\"%.*s\", "
|
||||
"response=\"%s\"",
|
||||
proxy?"Proxy-":"",
|
||||
userp_quoted,
|
||||
d->realm,
|
||||
d->nonce,
|
||||
uripath, /* this is the PATH part of the URL */
|
||||
urilen, uripath, /* this is the PATH part of the URL */
|
||||
request_digest);
|
||||
}
|
||||
Curl_safefree(userp_quoted);
|
||||
|
||||
@@ -145,8 +145,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
const char* protocol;
|
||||
CURLcode error;
|
||||
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
if(checkprefix("GSS-Negotiate", header)) {
|
||||
protocol = "GSS-Negotiate";
|
||||
gss = TRUE;
|
||||
|
||||
@@ -98,9 +98,6 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
|
||||
const char* protocol;
|
||||
CURLcode error;
|
||||
|
||||
while(*header && ISSPACE(*header))
|
||||
header++;
|
||||
|
||||
if(checkprefix("GSS-Negotiate", header)) {
|
||||
protocol = "GSS-Negotiate";
|
||||
gss = TRUE;
|
||||
|
||||
@@ -452,8 +452,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
(401 == k->httpcode)) ||
|
||||
(checkprefix("Proxy-authenticate:", line_start) &&
|
||||
(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)
|
||||
return result;
|
||||
}
|
||||
|
||||
247
lib/imap.c
247
lib/imap.c
@@ -27,6 +27,7 @@
|
||||
* RFC4959 IMAP Extension for SASL Initial Client Response
|
||||
* RFC5092 IMAP URL Scheme
|
||||
* 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 */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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()
|
||||
@@ -396,6 +426,7 @@ static void state(struct connectdata *conn, imapstate newstate)
|
||||
"AUTHENTICATE_NTLM",
|
||||
"AUTHENTICATE_NTLM_TYPE2MSG",
|
||||
"AUTHENTICATE_XOAUTH2",
|
||||
"AUTHENTICATE_CANCEL",
|
||||
"AUTHENTICATE_FINAL",
|
||||
"LOGIN",
|
||||
"LIST",
|
||||
@@ -553,8 +584,8 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Calculate the supported authentication mechanism by decreasing order of
|
||||
security */
|
||||
/* Calculate the supported authentication mechanism, by decreasing order of
|
||||
security, as well as the initial response where appropriate */
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if((imapc->authmechs & 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(mech) {
|
||||
if(mech && (imapc->preftype & IMAP_TYPE_SASL)) {
|
||||
/* Perform SASL based authentication */
|
||||
if(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);
|
||||
}
|
||||
else if(!imapc->login_disabled)
|
||||
else if((!imapc->login_disabled) &&
|
||||
(imapc->preftype & IMAP_TYPE_CLEARTEXT))
|
||||
/* Perform clear text authentication */
|
||||
result = imap_perform_login(conn);
|
||||
else {
|
||||
@@ -976,19 +1008,16 @@ static CURLcode imap_state_auth_plain_resp(struct connectdata *conn,
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
|
||||
&plainauth, &len);
|
||||
|
||||
if(!result && plainauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(plainauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", plainauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(plainauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1013,19 +1042,16 @@ static CURLcode imap_state_auth_login_resp(struct connectdata *conn,
|
||||
/* Create the user message */
|
||||
result = Curl_sasl_create_login_message(data, conn->user,
|
||||
&authuser, &len);
|
||||
|
||||
if(!result && authuser) {
|
||||
/* Send the user */
|
||||
if(!result) {
|
||||
if(authuser) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authuser);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_LOGIN_PASSWD);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authuser);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1050,19 +1076,16 @@ static CURLcode imap_state_auth_login_password_resp(struct connectdata *conn,
|
||||
/* Create the password message */
|
||||
result = Curl_sasl_create_login_message(data, conn->passwd,
|
||||
&authpasswd, &len);
|
||||
|
||||
if(!result && authpasswd) {
|
||||
/* Send the password */
|
||||
if(!result) {
|
||||
if(authpasswd) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", authpasswd);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authpasswd);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1075,9 +1098,10 @@ static CURLcode imap_state_auth_cram_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg = NULL;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(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;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
imap_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Terminate the challenge */
|
||||
if(*chlg64 != '=') {
|
||||
for(len = strlen(chlg64); len--;)
|
||||
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' &&
|
||||
chlg64[len] != '\t')
|
||||
break;
|
||||
/* Decode the challenge message */
|
||||
result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
|
||||
if(result) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
|
||||
|
||||
if(++len) {
|
||||
chlg64[len] = '\0';
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* 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);
|
||||
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
Curl_safefree(chlg);
|
||||
Curl_safefree(rplyb64);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1128,9 +1148,13 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
char nonce[64];
|
||||
char realm[128];
|
||||
char algorithm[64];
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -1139,26 +1163,35 @@ static CURLcode imap_state_auth_digest_resp(struct connectdata *conn,
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
imap_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Decode the challange message */
|
||||
result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
||||
realm, sizeof(realm),
|
||||
algorithm, sizeof(algorithm));
|
||||
if(result || strcmp(algorithm, "md5-sess") != 0) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", "*");
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_CANCEL);
|
||||
}
|
||||
else {
|
||||
/* Create the response message */
|
||||
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user,
|
||||
conn->passwd, "imap",
|
||||
&rplyb64, &len);
|
||||
|
||||
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
|
||||
conn->user, conn->passwd,
|
||||
"imap", &rplyb64, &len);
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_DIGESTMD5_RESP);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1211,19 +1244,16 @@ static CURLcode imap_state_auth_ntlm_resp(struct connectdata *conn,
|
||||
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type1msg, &len);
|
||||
|
||||
if(!result && type1msg) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(type1msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type1msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_NTLM_TYPE2MSG);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type1msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1235,8 +1265,9 @@ static CURLcode imap_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
size_t len = 0;
|
||||
char *type2msg = NULL;
|
||||
char *type3msg = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(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;
|
||||
}
|
||||
else {
|
||||
/* Create the type-3 message */
|
||||
result = Curl_sasl_create_ntlm_type3_message(data,
|
||||
data->state.buffer + 2,
|
||||
conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type3msg, &len);
|
||||
/* Get the challenge message */
|
||||
imap_get_message(data->state.buffer, &type2msg);
|
||||
|
||||
/* Decode the type-2 message */
|
||||
result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
|
||||
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 */
|
||||
if(!result) {
|
||||
if(type3msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", type3msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type3msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#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,
|
||||
int imapcode,
|
||||
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,
|
||||
conn->xoauth2_bearer,
|
||||
&xoauth, &len);
|
||||
|
||||
if(!result && xoauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(xoauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.imapc.pp, "%s", xoauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, IMAP_AUTHENTICATE_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For final responses to the AUTHENTICATE sequence */
|
||||
/* 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,
|
||||
int imapcode,
|
||||
imapstate instate)
|
||||
@@ -1660,6 +1712,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
|
||||
result = imap_state_auth_xoauth2_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
|
||||
case IMAP_AUTHENTICATE_CANCEL:
|
||||
result = imap_state_auth_cancel_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
|
||||
case IMAP_AUTHENTICATE_FINAL:
|
||||
result = imap_state_auth_final_resp(conn, imapcode, imapc->state);
|
||||
break;
|
||||
@@ -1782,7 +1838,8 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
|
||||
pp->endofresp = imap_endofresp;
|
||||
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;
|
||||
|
||||
/* 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
|
||||
point! */
|
||||
if(!dead_connection && imapc->pp.conn)
|
||||
if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
|
||||
if(!imap_perform_logout(conn))
|
||||
(void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
|
||||
|
||||
@@ -2276,25 +2333,43 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
|
||||
if(strnequal(key, "AUTH", 4)) {
|
||||
const char *value = ptr + 1;
|
||||
|
||||
if(strequal(value, "*"))
|
||||
if(strequal(value, "*")) {
|
||||
imapc->preftype = IMAP_TYPE_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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
else
|
||||
}
|
||||
else {
|
||||
imapc->preftype = IMAP_TYPE_NONE;
|
||||
imapc->prefmech = SASL_AUTH_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
10
lib/imap.h
10
lib/imap.h
@@ -44,6 +44,7 @@ typedef enum {
|
||||
IMAP_AUTHENTICATE_NTLM,
|
||||
IMAP_AUTHENTICATE_NTLM_TYPE2MSG,
|
||||
IMAP_AUTHENTICATE_XOAUTH2,
|
||||
IMAP_AUTHENTICATE_CANCEL,
|
||||
IMAP_AUTHENTICATE_FINAL,
|
||||
IMAP_LOGIN,
|
||||
IMAP_LIST,
|
||||
@@ -77,6 +78,7 @@ struct imap_conn {
|
||||
imapstate state; /* Always use imap.c:state() to change state! */
|
||||
bool ssldone; /* Is connect() over SSL done? */
|
||||
unsigned int authmechs; /* Accepted authentication mechanisms */
|
||||
unsigned int preftype; /* Preferred authentication type */
|
||||
unsigned int prefmech; /* Preferred authentication mechanism */
|
||||
unsigned int authused; /* Auth mechanism used for the connection */
|
||||
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_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 */
|
||||
|
||||
33
lib/multi.c
33
lib/multi.c
@@ -41,6 +41,7 @@
|
||||
#include "bundles.h"
|
||||
#include "multihandle.h"
|
||||
#include "pipeline.h"
|
||||
#include "sigpipe.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -621,17 +622,28 @@ static int waitconnect_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int numsocks)
|
||||
{
|
||||
int i;
|
||||
int s=0;
|
||||
int rc=0;
|
||||
|
||||
if(!numsocks)
|
||||
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
|
||||
socket to become readable to be able to get the response headers */
|
||||
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
|
||||
return GETSOCK_READSOCK(0);
|
||||
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) {
|
||||
sock[0] = conn->sock[FIRSTSOCKET];
|
||||
rc = GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms))
|
||||
if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
|
||||
timeout_ms = (int)timeout_internal;
|
||||
|
||||
/* Count up how many fds we have from the multi handle */
|
||||
@@ -865,6 +877,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
|
||||
if(nfds) {
|
||||
/* wait... */
|
||||
infof(data, "Curl_poll(%d ds, %d ms)\n", nfds, timeout_ms);
|
||||
i = Curl_poll(ufds, nfds, timeout_ms);
|
||||
|
||||
if(i) {
|
||||
@@ -1774,12 +1787,18 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
|
||||
struct SessionHandle *nextdata;
|
||||
|
||||
if(GOOD_MULTI_HANDLE(multi)) {
|
||||
bool restore_pipe = FALSE;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
multi->type = 0; /* not good anymore */
|
||||
|
||||
/* Close all the connections in the connection cache */
|
||||
close_all_connections(multi);
|
||||
|
||||
if(multi->closure_handle) {
|
||||
sigpipe_ignore(multi->closure_handle, &pipe_st);
|
||||
restore_pipe = TRUE;
|
||||
|
||||
multi->closure_handle->dns.hostcache = multi->hostcache;
|
||||
Curl_hostcache_clean(multi->closure_handle,
|
||||
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);
|
||||
|
||||
free(multi);
|
||||
if(restore_pipe)
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#define MULTI_TIMEOUT_INACCURACY 3000
|
||||
#endif
|
||||
|
||||
#define MULTI_TIMEOUT_INACCURACY_MS (MULTI_TIMEOUT_INACCURACY / 1000)
|
||||
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
*/
|
||||
|
||||
175
lib/nss.c
175
lib/nss.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "curl_memory.h"
|
||||
#include "rawstr.h"
|
||||
#include "warnless.h"
|
||||
#include "x509asn1.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@@ -76,9 +77,7 @@ PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
|
||||
|
||||
PRLock * nss_initlock = NULL;
|
||||
PRLock * nss_crllock = NULL;
|
||||
#ifdef HAVE_NSS_INITCONTEXT
|
||||
NSSInitContext * nss_context = NULL;
|
||||
#endif
|
||||
|
||||
volatile int initialized = 0;
|
||||
|
||||
@@ -653,6 +652,10 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
|
||||
SSLChannelInfo channel;
|
||||
SSLCipherSuiteInfo suite;
|
||||
CERTCertificate *cert;
|
||||
CERTCertificate *cert2;
|
||||
CERTCertificate *cert3;
|
||||
PRTime now;
|
||||
int i;
|
||||
|
||||
if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
|
||||
SECSuccess && channel.length == sizeof channel &&
|
||||
@@ -663,11 +666,45 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
|
||||
}
|
||||
}
|
||||
|
||||
cert = SSL_PeerCertificate(sock);
|
||||
|
||||
if(cert) {
|
||||
infof(conn->data, "Server certificate:\n");
|
||||
|
||||
cert = SSL_PeerCertificate(sock);
|
||||
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;
|
||||
}
|
||||
@@ -854,7 +891,6 @@ isTLSIntoleranceError(PRInt32 err)
|
||||
|
||||
static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
|
||||
{
|
||||
#ifdef HAVE_NSS_INITCONTEXT
|
||||
NSSInitParameters initparams;
|
||||
|
||||
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));
|
||||
initparams.length = sizeof(initparams);
|
||||
#else /* HAVE_NSS_INITCONTEXT */
|
||||
SECStatus rv;
|
||||
|
||||
if(NSS_IsInitialized())
|
||||
return CURLE_OK;
|
||||
#endif
|
||||
|
||||
if(cert_dir) {
|
||||
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;
|
||||
|
||||
infof(data, "Initializing NSS with certpath: %s\n", certpath);
|
||||
#ifdef HAVE_NSS_INITCONTEXT
|
||||
nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
|
||||
NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
|
||||
free(certpath);
|
||||
|
||||
if(nss_context != NULL)
|
||||
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, "Initializing NSS with certpath: none\n");
|
||||
#ifdef HAVE_NSS_INITCONTEXT
|
||||
nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
|
||||
| NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
|
||||
| NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
|
||||
if(nss_context != NULL)
|
||||
return CURLE_OK;
|
||||
#else /* HAVE_NSS_INITCONTEXT */
|
||||
if(NSS_NoDB_Init(NULL) == SECSuccess)
|
||||
return CURLE_OK;
|
||||
#endif
|
||||
|
||||
infof(data, "Unable to initialize NSS\n");
|
||||
return CURLE_SSL_CACERT_BADFILE;
|
||||
@@ -1000,12 +1017,8 @@ void Curl_nss_cleanup(void)
|
||||
SECMOD_DestroyModule(mod);
|
||||
mod = NULL;
|
||||
}
|
||||
#ifdef HAVE_NSS_INITCONTEXT
|
||||
NSS_ShutdownContext(nss_context);
|
||||
nss_context = NULL;
|
||||
#else /* HAVE_NSS_INITCONTEXT */
|
||||
NSS_Shutdown();
|
||||
#endif
|
||||
}
|
||||
PR_Unlock(nss_initlock);
|
||||
|
||||
@@ -1172,13 +1185,69 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
|
||||
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)
|
||||
{
|
||||
PRErrorCode err = 0;
|
||||
PRFileDesc *model = NULL;
|
||||
PRBool ssl2 = PR_FALSE;
|
||||
PRBool ssl3 = PR_FALSE;
|
||||
PRBool tlsv1 = PR_FALSE;
|
||||
PRBool ssl_no_cache;
|
||||
PRBool ssl_cbc_random_iv;
|
||||
struct SessionHandle *data = conn->data;
|
||||
@@ -1190,6 +1259,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
long time_left;
|
||||
PRUint32 timeout;
|
||||
|
||||
SSLVersionRange sslver = {
|
||||
SSL_LIBRARY_VERSION_3_0, /* min */
|
||||
SSL_LIBRARY_VERSION_TLS_1_0 /* max */
|
||||
};
|
||||
|
||||
if(connssl->state == ssl_connection_complete)
|
||||
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)
|
||||
goto error;
|
||||
|
||||
/* do not use SSL cache if we are not going to verify peer */
|
||||
ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE;
|
||||
/* do not use SSL cache if disabled or we are not going to verify peer */
|
||||
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)
|
||||
goto error;
|
||||
|
||||
switch (data->set.ssl.version) {
|
||||
default:
|
||||
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)
|
||||
/* enable/disable the requested SSL version(s) */
|
||||
if(nss_init_sslver(&sslver, data) != CURLE_OK)
|
||||
goto error;
|
||||
if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
|
||||
goto error;
|
||||
if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
|
||||
if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
ssl_cbc_random_iv = !data->set.ssl_enable_beast;
|
||||
@@ -1466,7 +1517,9 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
Curl_llist_destroy(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() */
|
||||
data->state.ssl_connect_retry = TRUE;
|
||||
infof(data, "Error in TLS handshake, trying SSLv3...\n");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -526,7 +526,7 @@ static int parsedate(const char *date, time_t *output)
|
||||
/* Add the time zone diff between local time zone and GMT. */
|
||||
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 */
|
||||
|
||||
t += delta;
|
||||
|
||||
206
lib/pop3.c
206
lib/pop3.c
@@ -29,6 +29,7 @@
|
||||
* RFC4616 PLAIN authentication
|
||||
* RFC5034 POP3 SASL Authentication Mechanism
|
||||
* 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 */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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()
|
||||
@@ -375,6 +405,7 @@ static void state(struct connectdata *conn, pop3state newstate)
|
||||
"AUTH_NTLM",
|
||||
"AUTH_NTLM_TYPE2MSG",
|
||||
"AUTH_XOAUTH2",
|
||||
"AUTH_CANCEL",
|
||||
"AUTH_FINAL",
|
||||
"APOP",
|
||||
"USER",
|
||||
@@ -570,8 +601,8 @@ static CURLcode pop3_perform_authenticate(struct connectdata *conn)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Calculate the supported authentication mechanism by decreasing order of
|
||||
security */
|
||||
/* Calculate the supported authentication mechanism, by decreasing order of
|
||||
security, as well as the initial response where appropriate */
|
||||
if(pop3c->authtypes & POP3_TYPE_SASL) {
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||
@@ -834,19 +865,16 @@ static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_plain_message(data, conn->user, conn->passwd,
|
||||
&plainauth, &len);
|
||||
|
||||
if(!result && plainauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(plainauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", plainauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(plainauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -871,19 +899,16 @@ static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
|
||||
/* Create the user message */
|
||||
result = Curl_sasl_create_login_message(data, conn->user,
|
||||
&authuser, &len);
|
||||
|
||||
if(!result && authuser) {
|
||||
/* Send the user */
|
||||
if(!result) {
|
||||
if(authuser) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authuser);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_LOGIN_PASSWD);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authuser);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -908,19 +933,16 @@ static CURLcode pop3_state_auth_login_password_resp(struct connectdata *conn,
|
||||
/* Create the password message */
|
||||
result = Curl_sasl_create_login_message(data, conn->passwd,
|
||||
&authpasswd, &len);
|
||||
|
||||
if(!result && authpasswd) {
|
||||
/* Send the password */
|
||||
if(!result) {
|
||||
if(authpasswd) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", authpasswd);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authpasswd);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -933,9 +955,10 @@ static CURLcode pop3_state_auth_cram_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg = NULL;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(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;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
pop3_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Terminate the challenge */
|
||||
if(*chlg64 != '=') {
|
||||
for(len = strlen(chlg64); len--;)
|
||||
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' &&
|
||||
chlg64[len] != '\t')
|
||||
break;
|
||||
/* Decode the challenge message */
|
||||
result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
|
||||
if(result) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
|
||||
|
||||
if(++len) {
|
||||
chlg64[len] = '\0';
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* 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);
|
||||
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
Curl_safefree(chlg);
|
||||
Curl_safefree(rplyb64);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -986,9 +1005,13 @@ static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
char nonce[64];
|
||||
char realm[128];
|
||||
char algorithm[64];
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -997,26 +1020,35 @@ static CURLcode pop3_state_auth_digest_resp(struct connectdata *conn,
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 2; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
pop3_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Decode the challange message */
|
||||
result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
||||
realm, sizeof(realm),
|
||||
algorithm, sizeof(algorithm));
|
||||
if(result || strcmp(algorithm, "md5-sess") != 0) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", "*");
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_CANCEL);
|
||||
}
|
||||
else {
|
||||
/* Create the response message */
|
||||
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user,
|
||||
conn->passwd, "pop",
|
||||
&rplyb64, &len);
|
||||
|
||||
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
|
||||
conn->user, conn->passwd,
|
||||
"pop", &rplyb64, &len);
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_DIGESTMD5_RESP);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1069,19 +1101,16 @@ static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
|
||||
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type1msg, &len);
|
||||
|
||||
if(!result && type1msg) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(type1msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type1msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_NTLM_TYPE2MSG);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type1msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1093,8 +1122,9 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
size_t len = 0;
|
||||
char *type2msg = NULL;
|
||||
char *type3msg = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -1103,25 +1133,34 @@ static CURLcode pop3_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
}
|
||||
else {
|
||||
/* Create the type-3 message */
|
||||
result = Curl_sasl_create_ntlm_type3_message(data,
|
||||
data->state.buffer + 2,
|
||||
conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type3msg, &len);
|
||||
/* Get the type-2 message */
|
||||
pop3_get_message(data->state.buffer, &type2msg);
|
||||
|
||||
/* Decode the type-2 message */
|
||||
result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
|
||||
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 */
|
||||
if(!result) {
|
||||
if(type3msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", type3msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type3msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1147,24 +1186,36 @@ static CURLcode pop3_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&xoauth, &len);
|
||||
|
||||
if(!result && xoauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(xoauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s", xoauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, POP3_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For final responses to the AUTH sequence */
|
||||
/* 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,
|
||||
int pop3code,
|
||||
pop3state instate)
|
||||
@@ -1386,6 +1437,10 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
|
||||
result = pop3_state_auth_xoauth2_resp(conn, pop3code, pop3c->state);
|
||||
break;
|
||||
|
||||
case POP3_AUTH_CANCEL:
|
||||
result = pop3_state_auth_cancel_resp(conn, pop3code, pop3c->state);
|
||||
break;
|
||||
|
||||
case POP3_AUTH_FINAL:
|
||||
result = pop3_state_auth_final_resp(conn, pop3code, pop3c->state);
|
||||
break;
|
||||
@@ -1570,12 +1625,12 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
|
||||
{
|
||||
/* This is POP3 and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct POP3 *pop3 = conn->data->req.protop;
|
||||
|
||||
DEBUGF(infof(conn->data, "DO phase starts\n"));
|
||||
|
||||
if(conn->data->set.opt_no_body) {
|
||||
/* Requested no body means no transfer */
|
||||
struct POP3 *pop3 = conn->data->req.protop;
|
||||
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
|
||||
* resources. BLOCKING.
|
||||
*/
|
||||
static CURLcode pop3_disconnect(struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
{
|
||||
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
|
||||
point! */
|
||||
if(!dead_connection && pop3c->pp.conn)
|
||||
if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart)
|
||||
if(!pop3_perform_quit(conn))
|
||||
(void)pop3_block_statemach(conn); /* ignore errors on QUIT */
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ typedef enum {
|
||||
POP3_AUTH_NTLM,
|
||||
POP3_AUTH_NTLM_TYPE2MSG,
|
||||
POP3_AUTH_XOAUTH2,
|
||||
POP3_AUTH_CANCEL,
|
||||
POP3_AUTH_FINAL,
|
||||
POP3_APOP,
|
||||
POP3_USER,
|
||||
@@ -92,7 +93,7 @@ extern const struct Curl_handler Curl_handler_pop3s;
|
||||
|
||||
/* Authentication type values */
|
||||
#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 */
|
||||
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
|
||||
|
||||
@@ -204,6 +204,12 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
|
||||
case CURL_SSLVERSION_SSLv3:
|
||||
h->protocol = SSL_VERSION_3;
|
||||
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;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
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 <netdb.h>
|
||||
@@ -42,7 +42,8 @@ typedef unsigned long u_int32_t;
|
||||
#include <qsoasync.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,
|
||||
struct addrinfo * * res);
|
||||
#define getaddrinfo Curl_getaddrinfo_a
|
||||
@@ -66,7 +67,8 @@ extern int Curl_SSL_Init_a(SSLInit * init);
|
||||
#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
|
||||
|
||||
|
||||
@@ -226,5 +228,12 @@ extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
|
||||
#define sendto Curl_os400_sendto
|
||||
#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 */
|
||||
|
||||
78
lib/sigpipe.h
Normal file
78
lib/sigpipe.h
Normal 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 */
|
||||
525
lib/smtp.c
525
lib/smtp.c
@@ -27,7 +27,8 @@
|
||||
* RFC4954 SMTP Authentication
|
||||
* RFC5321 SMTP protocol
|
||||
* 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_parse_url_options(struct connectdata *conn);
|
||||
static CURLcode smtp_parse_url_path(struct connectdata *conn);
|
||||
static CURLcode smtp_parse_custom_request(struct connectdata *conn);
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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;
|
||||
bool result = FALSE;
|
||||
size_t wordlen;
|
||||
|
||||
/* Nothing for us */
|
||||
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? */
|
||||
result = (line[3] == ' ') ? TRUE : FALSE;
|
||||
if(result)
|
||||
/* Do we have a command response? This should be the response code followed
|
||||
by a space and optionally some text as per RFC-5321 and as outlined in
|
||||
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));
|
||||
|
||||
/* Are we processing EHLO command data? */
|
||||
if(smtpc->state == SMTP_EHLO && (!result || (result && *resp/100 == 2))) {
|
||||
line += 4;
|
||||
len -= 4;
|
||||
|
||||
/* Does the server support the STARTTLS capability? */
|
||||
if(len >= 8 && !memcmp(line, "STARTTLS", 8))
|
||||
smtpc->tls_supported = TRUE;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* Make sure real server never sends internal value */
|
||||
if(*resp == 1)
|
||||
*resp = 0;
|
||||
}
|
||||
/* Do we have a multiline (continuation) response? */
|
||||
else if(line[3] == '-' &&
|
||||
(smtpc->state == SMTP_EHLO || smtpc->state == SMTP_COMMAND)) {
|
||||
result = TRUE;
|
||||
*resp = 1; /* Internal response code */
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -330,7 +314,9 @@ static void state(struct connectdata *conn, smtpstate newstate)
|
||||
"AUTH_NTLM",
|
||||
"AUTH_NTLM_TYPE2MSG",
|
||||
"AUTH_XOAUTH2",
|
||||
"AUTH_CANCEL",
|
||||
"AUTH_FINAL",
|
||||
"COMMAND",
|
||||
"MAIL",
|
||||
"RCPT",
|
||||
"DATA",
|
||||
@@ -565,6 +551,35 @@ static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||
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()
|
||||
@@ -656,7 +671,6 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
/* Send the RCPT TO command */
|
||||
if(smtp->rcpt) {
|
||||
if(smtp->rcpt->data[0] == '<')
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
|
||||
smtp->rcpt->data);
|
||||
@@ -665,7 +679,6 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
|
||||
smtp->rcpt->data);
|
||||
if(!result)
|
||||
state(conn, SMTP_RCPT);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -740,10 +753,13 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
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 */
|
||||
|
||||
if(smtpcode/100 != 2) {
|
||||
if(smtpcode/100 != 2 && smtpcode != 1) {
|
||||
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
|
||||
!conn->bits.user_passwd)
|
||||
result = smtp_perform_helo(conn);
|
||||
@@ -752,7 +768,67 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
||||
result = CURLE_REMOTE_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||
else {
|
||||
line += 4;
|
||||
len -= 4;
|
||||
|
||||
/* Does the server support the STARTTLS capability? */
|
||||
if(len >= 8 && !memcmp(line, "STARTTLS", 8))
|
||||
smtpc->tls_supported = TRUE;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
@@ -767,6 +843,8 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
||||
}
|
||||
else
|
||||
result = smtp_perform_authenticate(conn);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -811,19 +889,16 @@ static CURLcode smtp_state_auth_plain_resp(struct connectdata *conn,
|
||||
/* Create the authorisation message */
|
||||
result = Curl_sasl_create_plain_message(conn->data, conn->user,
|
||||
conn->passwd, &plainauth, &len);
|
||||
|
||||
if(!result && plainauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(plainauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(plainauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -848,19 +923,16 @@ static CURLcode smtp_state_auth_login_resp(struct connectdata *conn,
|
||||
/* Create the user message */
|
||||
result = Curl_sasl_create_login_message(conn->data, conn->user,
|
||||
&authuser, &len);
|
||||
|
||||
if(!result && authuser) {
|
||||
/* Send the user */
|
||||
if(!result) {
|
||||
if(authuser) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_LOGIN_PASSWD);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authuser);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -885,19 +957,16 @@ static CURLcode smtp_state_auth_login_password_resp(struct connectdata *conn,
|
||||
/* Create the password message */
|
||||
result = Curl_sasl_create_login_message(conn->data, conn->passwd,
|
||||
&authpasswd, &len);
|
||||
|
||||
if(!result && authpasswd) {
|
||||
/* Send the password */
|
||||
if(!result) {
|
||||
if(authpasswd) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(authpasswd);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -910,9 +979,10 @@ static CURLcode smtp_state_auth_cram_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg = NULL;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
(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;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
smtp_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Terminate the challenge */
|
||||
if(*chlg64 != '=') {
|
||||
for(len = strlen(chlg64); len--;)
|
||||
if(chlg64[len] != '\r' && chlg64[len] != '\n' && chlg64[len] != ' ' &&
|
||||
chlg64[len] != '\t')
|
||||
break;
|
||||
/* Decode the challenge message */
|
||||
result = Curl_sasl_decode_cram_md5_message(chlg64, &chlg, &len);
|
||||
if(result) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
|
||||
|
||||
if(++len) {
|
||||
chlg64[len] = '\0';
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* 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);
|
||||
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
Curl_safefree(chlg);
|
||||
Curl_safefree(rplyb64);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -963,9 +1029,13 @@ static CURLcode smtp_state_auth_digest_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *chlg64 = data->state.buffer;
|
||||
size_t len = 0;
|
||||
char *chlg64 = NULL;
|
||||
char *rplyb64 = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
char nonce[64];
|
||||
char realm[128];
|
||||
char algorithm[64];
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@@ -974,26 +1044,35 @@ static CURLcode smtp_state_auth_digest_resp(struct connectdata *conn,
|
||||
return CURLE_LOGIN_DENIED;
|
||||
}
|
||||
|
||||
/* Get the challenge */
|
||||
for(chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
|
||||
;
|
||||
/* Get the challenge message */
|
||||
smtp_get_message(data->state.buffer, &chlg64);
|
||||
|
||||
/* Decode the challange message */
|
||||
result = Curl_sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
|
||||
realm, sizeof(realm),
|
||||
algorithm, sizeof(algorithm));
|
||||
if(result || strcmp(algorithm, "md5-sess") != 0) {
|
||||
/* Send the cancellation */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "*");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_CANCEL);
|
||||
}
|
||||
else {
|
||||
/* Create the response message */
|
||||
result = Curl_sasl_create_digest_md5_message(data, chlg64, conn->user,
|
||||
conn->passwd, "smtp",
|
||||
&rplyb64, &len);
|
||||
|
||||
result = Curl_sasl_create_digest_md5_message(data, nonce, realm,
|
||||
conn->user, conn->passwd,
|
||||
"smtp", &rplyb64, &len);
|
||||
if(!result && rplyb64) {
|
||||
/* Send the response */
|
||||
if(!result) {
|
||||
if(rplyb64) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_DIGESTMD5_RESP);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(rplyb64);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1047,19 +1126,16 @@ static CURLcode smtp_state_auth_ntlm_resp(struct connectdata *conn,
|
||||
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type1msg, &len);
|
||||
|
||||
if(!result && type1msg) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(type1msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type1msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_NTLM_TYPE2MSG);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type1msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1071,6 +1147,7 @@ static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
char *type2msg = NULL;
|
||||
char *type3msg = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
@@ -1081,25 +1158,34 @@ static CURLcode smtp_state_auth_ntlm_type2msg_resp(struct connectdata *conn,
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
}
|
||||
else {
|
||||
/* Create the type-3 message */
|
||||
result = Curl_sasl_create_ntlm_type3_message(data,
|
||||
data->state.buffer + 4,
|
||||
conn->user, conn->passwd,
|
||||
&conn->ntlm,
|
||||
&type3msg, &len);
|
||||
/* Get the type-2 message */
|
||||
smtp_get_message(data->state.buffer, &type2msg);
|
||||
|
||||
/* Decode the type-2 message */
|
||||
result = Curl_sasl_decode_ntlm_type2_message(data, type2msg, &conn->ntlm);
|
||||
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 */
|
||||
if(!result) {
|
||||
if(type3msg) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", type3msg);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(type3msg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1125,24 +1211,36 @@ static CURLcode smtp_state_auth_xoauth2_resp(struct connectdata *conn,
|
||||
result = Curl_sasl_create_xoauth2_message(conn->data, conn->user,
|
||||
conn->xoauth2_bearer,
|
||||
&xoauth, &len);
|
||||
|
||||
if(!result && xoauth) {
|
||||
/* Send the message */
|
||||
if(!result) {
|
||||
if(xoauth) {
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", xoauth);
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_AUTH_FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(xoauth);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For the final responses to the AUTH sequence */
|
||||
/* 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,
|
||||
int smtpcode,
|
||||
smtpstate instate)
|
||||
@@ -1163,26 +1261,68 @@ static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
|
||||
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 */
|
||||
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
||||
smtpstate instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(smtpcode/100 != 2) {
|
||||
failf(data, "MAIL failed: %d", smtpcode);
|
||||
result = CURLE_SEND_ERROR;
|
||||
state(conn, SMTP_STOP);
|
||||
}
|
||||
else {
|
||||
smtp->rcpt = data->set.mail_rcpt;
|
||||
|
||||
else
|
||||
/* Start the RCPT TO command */
|
||||
result = smtp_perform_rcpt_to(conn);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1200,24 +1340,21 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
||||
if(smtpcode/100 != 2) {
|
||||
failf(data, "RCPT failed: %d", smtpcode);
|
||||
result = CURLE_SEND_ERROR;
|
||||
state(conn, SMTP_STOP);
|
||||
}
|
||||
else {
|
||||
if(smtp->rcpt) {
|
||||
smtp->rcpt = smtp->rcpt->next;
|
||||
|
||||
if(smtp->rcpt)
|
||||
/* Send the next RCPT TO command */
|
||||
result = smtp_perform_rcpt_to(conn);
|
||||
|
||||
/* If we failed or still are sending RCPT data then return */
|
||||
if(result || smtp->rcpt)
|
||||
return result;
|
||||
}
|
||||
|
||||
else {
|
||||
/* Send the DATA command */
|
||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
|
||||
|
||||
if(!result)
|
||||
state(conn, SMTP_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1226,15 +1363,16 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
||||
static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
|
||||
smtpstate instate)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(smtpcode != 354) {
|
||||
state(conn, SMTP_STOP);
|
||||
return CURLE_SEND_ERROR;
|
||||
failf(data, "DATA failed: %d", smtpcode);
|
||||
result = CURLE_SEND_ERROR;
|
||||
}
|
||||
|
||||
else {
|
||||
/* Set the progress upload size */
|
||||
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||
|
||||
@@ -1243,8 +1381,9 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
|
||||
|
||||
/* End of DO phase */
|
||||
state(conn, SMTP_STOP);
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return Curl_pp_flushsend(pp);
|
||||
|
||||
do {
|
||||
/* Read the response from the server */
|
||||
result = Curl_pp_readresp(sock, pp, &smtpcode, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Store the latest response for later retrieval */
|
||||
if(smtpc->state != SMTP_QUIT)
|
||||
/* Store the latest response for later retrieval if necessary */
|
||||
if(smtpc->state != SMTP_QUIT && smtpcode != 1)
|
||||
data->info.httpcode = smtpcode;
|
||||
|
||||
if(smtpcode) {
|
||||
if(!smtpcode)
|
||||
break;
|
||||
|
||||
/* We have now received a full SMTP server response */
|
||||
switch(smtpc->state) {
|
||||
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);
|
||||
break;
|
||||
|
||||
case SMTP_AUTH_CANCEL:
|
||||
result = smtp_state_auth_cancel_resp(conn, smtpcode, smtpc->state);
|
||||
break;
|
||||
|
||||
case SMTP_AUTH_FINAL:
|
||||
result = smtp_state_auth_final_resp(conn, smtpcode, smtpc->state);
|
||||
break;
|
||||
|
||||
case SMTP_COMMAND:
|
||||
result = smtp_state_command_resp(conn, smtpcode, smtpc->state);
|
||||
break;
|
||||
|
||||
case SMTP_MAIL:
|
||||
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
|
||||
break;
|
||||
@@ -1381,7 +1531,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
|
||||
state(conn, SMTP_STOP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1521,7 +1671,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
conn->bits.close = TRUE; /* marked for closure */
|
||||
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
|
||||
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. */
|
||||
@@ -1560,6 +1710,9 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
result = smtp_block_statemach(conn);
|
||||
}
|
||||
|
||||
/* Cleanup our per-request based variables */
|
||||
Curl_safefree(smtp->custom);
|
||||
|
||||
/* Clear the transfer mode for the next request */
|
||||
smtp->transfer = FTPTRANSFER_BODY;
|
||||
|
||||
@@ -1570,31 +1723,41 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
||||
*
|
||||
* smtp_perform()
|
||||
*
|
||||
* This is the actual DO function for SMTP. Send a mail according to the
|
||||
* options previously setup.
|
||||
* This is the actual DO function for SMTP. Transfer a mail, send a command
|
||||
* or get some data according to the options previously setup.
|
||||
*/
|
||||
static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
||||
bool *dophase_done)
|
||||
{
|
||||
/* This is SMTP and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct SMTP *smtp = data->req.protop;
|
||||
|
||||
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 */
|
||||
struct SMTP *smtp = conn->data->req.protop;
|
||||
smtp->transfer = FTPTRANSFER_INFO;
|
||||
}
|
||||
|
||||
*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 */
|
||||
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)
|
||||
return result;
|
||||
|
||||
/* run the state-machine */
|
||||
/* Run the state-machine */
|
||||
result = smtp_multi_statemach(conn, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
@@ -1620,6 +1783,11 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
|
||||
|
||||
*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);
|
||||
|
||||
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
|
||||
* resources. BLOCKING.
|
||||
*/
|
||||
static CURLcode smtp_disconnect(struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
{
|
||||
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
|
||||
point! */
|
||||
if(!dead_connection && smtpc->pp.conn)
|
||||
if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart)
|
||||
if(!smtp_perform_quit(conn))
|
||||
(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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
/* When sending a SMTP payload we must detect CRLF. sequences making sure
|
||||
|
||||
@@ -45,7 +45,9 @@ typedef enum {
|
||||
SMTP_AUTH_NTLM,
|
||||
SMTP_AUTH_NTLM_TYPE2MSG,
|
||||
SMTP_AUTH_XOAUTH2,
|
||||
SMTP_AUTH_CANCEL,
|
||||
SMTP_AUTH_FINAL,
|
||||
SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */
|
||||
SMTP_MAIL, /* MAIL FROM */
|
||||
SMTP_RCPT, /* RCPT TO */
|
||||
SMTP_DATA,
|
||||
@@ -60,6 +62,7 @@ typedef enum {
|
||||
used. */
|
||||
struct SMTP {
|
||||
curl_pp_transfer transfer;
|
||||
char *custom; /* Custom Request */
|
||||
struct curl_slist *rcpt; /* Recipient list */
|
||||
size_t eob; /* Number of bytes of the EOB (End Of Body) that
|
||||
have been received so far */
|
||||
|
||||
@@ -129,6 +129,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
|
||||
curlx_nonblock(sock, FALSE);
|
||||
|
||||
infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
|
||||
|
||||
/*
|
||||
* Compose socks4 request
|
||||
*
|
||||
@@ -182,6 +184,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
|
||||
else
|
||||
hp = NULL; /* fail! */
|
||||
|
||||
infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
|
||||
|
||||
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
|
||||
|
||||
}
|
||||
|
||||
12
lib/ssh.c
12
lib/ssh.c
@@ -754,7 +754,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
curlx_uztoui(strlen(conn->user)));
|
||||
|
||||
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) {
|
||||
rc = LIBSSH2_ERROR_EAGAIN;
|
||||
break;
|
||||
@@ -2719,6 +2725,10 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
|
||||
CURLcode result;
|
||||
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
|
||||
function to make the re-use checks properly be able to check this bit. */
|
||||
conn->bits.close = FALSE;
|
||||
|
||||
17
lib/sslgen.c
17
lib/sslgen.c
@@ -611,6 +611,9 @@ int Curl_ssl_init_certinfo(struct SessionHandle * data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'value' is NOT a zero terminated string
|
||||
*/
|
||||
CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
|
||||
int certnum,
|
||||
const char *label,
|
||||
@@ -621,12 +624,22 @@ CURLcode Curl_ssl_push_certinfo_len(struct SessionHandle *data,
|
||||
char * output;
|
||||
struct curl_slist * nl;
|
||||
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 = curl_maprintf("%s:%.*s", label, valuelen, value);
|
||||
output = malloc(outlen);
|
||||
if(!output)
|
||||
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);
|
||||
if(!nl) {
|
||||
free(output);
|
||||
|
||||
63
lib/ssluse.c
63
lib/ssluse.c
@@ -1431,19 +1431,12 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
switch(data->set.ssl.version) {
|
||||
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:
|
||||
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);
|
||||
break;
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
@@ -1556,9 +1549,51 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
#endif
|
||||
|
||||
/* disable SSLv2 in the default case (i.e. allow SSLv3 and TLSv1) */
|
||||
if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT)
|
||||
switch(data->set.ssl.version) {
|
||||
case CURL_SSLVERSION_DEFAULT:
|
||||
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);
|
||||
|
||||
|
||||
@@ -1256,7 +1256,7 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
|
||||
if(*dophase_done) {
|
||||
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
|
||||
provide it for TFTP since it may do the entire transfer in this
|
||||
state. */
|
||||
|
||||
@@ -1309,10 +1309,11 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
|
||||
Curl_pgrsStartNow(data);
|
||||
|
||||
if(data->set.timeout)
|
||||
Curl_expire(data, data->set.timeout);
|
||||
Curl_expire(data, data->set.timeout + MULTI_TIMEOUT_INACCURACY_MS);
|
||||
|
||||
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 the session we need to make sure we only use the one(s) we now
|
||||
|
||||
132
lib/url.c
132
lib/url.c
@@ -299,13 +299,11 @@ static CURLcode setstropt(char **charp, char *s)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
|
||||
char **optionsp)
|
||||
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *user = NULL;
|
||||
char *passwd = NULL;
|
||||
char *options = NULL;
|
||||
|
||||
/* Parse the login details if specified. It not then we treat NULL as a hint
|
||||
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),
|
||||
(userp ? &user : NULL),
|
||||
(passwdp ? &passwd : NULL),
|
||||
(optionsp ? &options : NULL));
|
||||
NULL);
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
@@ -335,12 +333,6 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
|
||||
Curl_safefree(*passwdp);
|
||||
*passwdp = passwd;
|
||||
}
|
||||
|
||||
/* Store the options part of option if required */
|
||||
if(optionsp) {
|
||||
Curl_safefree(*optionsp);
|
||||
*optionsp = options;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1553,13 +1545,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
|
||||
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 *),
|
||||
&data->set.str[STRING_USERNAME],
|
||||
&data->set.str[STRING_PASSWORD],
|
||||
&data->set.str[STRING_OPTIONS]);
|
||||
&data->set.str[STRING_PASSWORD]);
|
||||
break;
|
||||
|
||||
case CURLOPT_USERNAME:
|
||||
/*
|
||||
* 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],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
|
||||
case CURLOPT_PASSWORD:
|
||||
/*
|
||||
* 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],
|
||||
va_arg(param, char *));
|
||||
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:
|
||||
/*
|
||||
* 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],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
|
||||
case CURLOPT_POSTQUOTE:
|
||||
/*
|
||||
* 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 *),
|
||||
&data->set.str[STRING_PROXYUSERNAME],
|
||||
&data->set.str[STRING_PROXYPASSWORD], NULL);
|
||||
&data->set.str[STRING_PROXYPASSWORD]);
|
||||
break;
|
||||
case CURLOPT_PROXYUSERNAME:
|
||||
/*
|
||||
@@ -1926,7 +1929,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
data->set.ssl.fsslctxp = va_arg(param, void *);
|
||||
break;
|
||||
#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:
|
||||
data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
|
||||
break;
|
||||
@@ -2502,6 +2506,10 @@ static void conn_free(struct connectdata *conn)
|
||||
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
|
||||
if(CURL_SOCKET_BAD != 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)
|
||||
Curl_ntlm_wb_cleanup(conn);
|
||||
@@ -3219,9 +3227,12 @@ static CURLcode ConnectionStore(struct SessionHandle *data,
|
||||
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;
|
||||
|
||||
switch(conn->proxytype) {
|
||||
@@ -3252,49 +3263,6 @@ CURLcode Curl_connected_proxy(struct connectdata *conn)
|
||||
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
|
||||
*/
|
||||
@@ -3561,6 +3529,8 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
|
||||
|
||||
conn->sock[FIRSTSOCKET] = 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->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,
|
||||
const char *user, const char *passwd,
|
||||
@@ -5598,41 +5568,10 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
|
||||
is later set again for the progress meter purpose */
|
||||
conn->now = Curl_tvnow();
|
||||
|
||||
for(;;) {
|
||||
/* loop for CURL_SERVER_CLOSED_CONNECTION */
|
||||
|
||||
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
||||
/* Try to connect only if not already connected */
|
||||
bool connected = FALSE;
|
||||
|
||||
result = ConnectPlease(data, conn, &connected);
|
||||
|
||||
if(result && !conn->ip_addr) {
|
||||
/* transport connection failure not related with authentication */
|
||||
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
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)
|
||||
result = Curl_connecthost(conn, conn->dns_entry);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
@@ -5640,11 +5579,8 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
|
||||
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;
|
||||
Curl_verboseconnect(conn);
|
||||
}
|
||||
|
||||
conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
|
||||
|
||||
@@ -70,7 +70,7 @@ void Curl_close_connections(struct SessionHandle *data);
|
||||
#define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi
|
||||
service */
|
||||
|
||||
CURLcode Curl_connected_proxy(struct connectdata *conn);
|
||||
CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
|
||||
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
#define Curl_verboseconnect(x) Curl_nop_stmt
|
||||
|
||||
@@ -838,6 +838,7 @@ struct connectdata {
|
||||
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() */
|
||||
Curl_addrinfo *ip_addr;
|
||||
Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
|
||||
|
||||
/* '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
|
||||
@@ -889,6 +890,7 @@ struct connectdata {
|
||||
struct timeval created; /* creation time */
|
||||
curl_socket_t sock[2]; /* two sockets, the second is used for the data
|
||||
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
|
||||
accept() */
|
||||
Curl_recv *recv[2];
|
||||
@@ -1635,6 +1637,8 @@ struct SessionHandle {
|
||||
other dynamic purposes */
|
||||
struct WildcardData wildcard; /* wildcard download state info */
|
||||
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)
|
||||
iconv_t outbound_cd; /* for translating to the network encoding */
|
||||
iconv_t inbound_cd; /* for translating from the network encoding */
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#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 "urldata.h"
|
||||
@@ -252,7 +252,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
|
||||
size_t inlength = end - from;
|
||||
int size = 1;
|
||||
size_t outlength;
|
||||
int chsize;
|
||||
int charsize;
|
||||
unsigned int wc;
|
||||
char * buf;
|
||||
|
||||
@@ -305,7 +305,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
|
||||
default: /* case 1: */
|
||||
wc = (wc << 8) | *(const unsigned char *) from++;
|
||||
}
|
||||
chsize = 1;
|
||||
charsize = 1;
|
||||
if(wc >= 0x00000080) {
|
||||
if(wc >= 0x00000800) {
|
||||
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));
|
||||
wc = (wc >> 6) | 0x00010000;
|
||||
chsize++;
|
||||
charsize++;
|
||||
}
|
||||
buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
|
||||
wc = (wc >> 6) | 0x00000800;
|
||||
chsize++;
|
||||
charsize++;
|
||||
}
|
||||
buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
|
||||
wc = (wc >> 6) | 0x000000C0;
|
||||
chsize++;
|
||||
charsize++;
|
||||
}
|
||||
buf[outlength] = (char) wc;
|
||||
outlength += chsize;
|
||||
outlength += charsize;
|
||||
}
|
||||
}
|
||||
buf[outlength] = '\0';
|
||||
@@ -812,7 +812,9 @@ static void do_pubkey_field(struct SessionHandle *data, int certnum,
|
||||
|
||||
output = Curl_ASN1tostr(elem, 0);
|
||||
if(output) {
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, label, output);
|
||||
if(!certnum)
|
||||
infof(data, " %s: %s\n", label, output);
|
||||
free((char *) output);
|
||||
}
|
||||
@@ -845,12 +847,15 @@ static void do_pubkey(struct SessionHandle * data, int certnum,
|
||||
len--;
|
||||
if(len > 32)
|
||||
elem.beg = q; /* Strip leading zero bytes. */
|
||||
if(!certnum)
|
||||
infof(data, " RSA Public Key (%lu bits)\n", len);
|
||||
if(data->set.ssl.certinfo) {
|
||||
q = curl_maprintf("%lu", len);
|
||||
if(q) {
|
||||
Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
|
||||
free((char *) q);
|
||||
}
|
||||
}
|
||||
/* Generate coefficients. */
|
||||
do_pubkey_field(data, certnum, "rsa(n)", &elem);
|
||||
Curl_getASN1Element(&elem, p, pk.end);
|
||||
@@ -896,6 +901,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
if(!data->set.ssl.certinfo)
|
||||
if(certnum)
|
||||
return CURLE_OK;
|
||||
|
||||
/* Prepare the certificate information for curl_easy_getinfo(). */
|
||||
|
||||
/* Extract the certificate ASN.1 elements. */
|
||||
@@ -905,7 +914,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
ccp = Curl_DNtostr(&cert.subject);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
|
||||
if(!certnum)
|
||||
infof(data, "%2d Subject: %s\n", certnum, ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -913,7 +924,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
ccp = Curl_DNtostr(&cert.issuer);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
|
||||
if(!certnum)
|
||||
infof(data, " Issuer: %s\n", ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -921,18 +934,23 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
version = 0;
|
||||
for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
|
||||
version = (version << 8) | *(const unsigned char *) ccp;
|
||||
if(data->set.ssl.certinfo) {
|
||||
ccp = curl_maprintf("%lx", version);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
|
||||
free((char *) ccp);
|
||||
}
|
||||
if(!certnum)
|
||||
infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
|
||||
|
||||
/* Serial number. */
|
||||
ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
|
||||
if(!certnum)
|
||||
infof(data, " Serial Number: %s\n", ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -941,7 +959,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
cert.signatureAlgorithm.end);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
|
||||
if(!certnum)
|
||||
infof(data, " Signature Algorithm: %s\n", ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -949,7 +969,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
ccp = Curl_ASN1tostr(&cert.notBefore, 0);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
|
||||
if(!certnum)
|
||||
infof(data, " Start Date: %s\n", ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -957,7 +979,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
ccp = Curl_ASN1tostr(&cert.notAfter, 0);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
|
||||
if(!certnum)
|
||||
infof(data, " Expire Date: %s\n", ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -966,7 +990,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
cert.subjectPublicKeyAlgorithm.end);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
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, ¶m, &cert.subjectPublicKey);
|
||||
free((char *) ccp);
|
||||
@@ -977,7 +1003,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
ccp = Curl_ASN1tostr(&cert.signature, 0);
|
||||
if(!ccp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
|
||||
if(!certnum)
|
||||
infof(data, " Signature: %s\n", ccp);
|
||||
free((char *) ccp);
|
||||
|
||||
@@ -987,7 +1015,7 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
&cp1, &cl1);
|
||||
if(cc != CURLE_OK)
|
||||
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
|
||||
<max 64 base64 characters>\n
|
||||
.
|
||||
@@ -1008,7 +1036,9 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
|
||||
cp2[i] = '\0';
|
||||
free(cp1);
|
||||
if(data->set.ssl.certinfo)
|
||||
Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
|
||||
if(!certnum)
|
||||
infof(data, "%s\n", cp2);
|
||||
free(cp2);
|
||||
return CURLE_OK;
|
||||
@@ -1148,4 +1178,4 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
|
||||
#endif /* USE_QSOSSL or USE_GSKIT */
|
||||
#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_QSOSSL) || defined(USE_GSKIT)
|
||||
#if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
|
||||
|
||||
#include "urldata.h"
|
||||
|
||||
@@ -125,5 +125,5 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
|
||||
CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
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 */
|
||||
|
||||
@@ -85,6 +85,7 @@ options:
|
||||
CURLOPT_ISSUERCERT
|
||||
CURLOPT_KEYPASSWD
|
||||
CURLOPT_KRBLEVEL
|
||||
CURLOPT_LOGIN_OPTIONS
|
||||
CURLOPT_MAIL_FROM
|
||||
CURLOPT_MAIL_AUTH
|
||||
CURLOPT_NETRC_FILE
|
||||
@@ -118,6 +119,7 @@ options:
|
||||
CURLOPT_USERAGENT
|
||||
CURLOPT_USERNAME
|
||||
CURLOPT_USERPWD
|
||||
CURLOPT_XOAUTH2_BEARER
|
||||
Else it is the same as for curl_easy_setopt().
|
||||
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.
|
||||
|
||||
@@ -77,7 +77,8 @@ makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
|
||||
|
||||
|
||||
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];
|
||||
@@ -407,7 +408,7 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
|
||||
compiler seems to compare string values after substitution. */
|
||||
|
||||
#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
|
||||
|
||||
/* If caller has been compiled with a new version, error. */
|
||||
@@ -647,13 +648,15 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
|
||||
|
||||
case CURLINFO_SLIST:
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
if(info == CURLINFO_CERTINFO) {
|
||||
switch (info) {
|
||||
case CURLINFO_CERTINFO:
|
||||
cipf = *(struct curl_certinfo * *) paramp;
|
||||
if(cipf) {
|
||||
if(!(cipt = (struct curl_certinfo *) malloc(sizeof *cipt)))
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
else {
|
||||
cipt->certinfo = (struct curl_slist * *) calloc(cipf->num_of_certs +
|
||||
cipt->certinfo = (struct curl_slist * *)
|
||||
calloc(cipf->num_of_certs +
|
||||
1, sizeof(struct curl_slist *));
|
||||
if(!cipt->certinfo)
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
@@ -677,12 +680,18 @@ curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
|
||||
|
||||
*(struct curl_certinfo * *) paramp = cipt;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
break;
|
||||
|
||||
case CURLINFO_TLS_SESSION:
|
||||
break;
|
||||
|
||||
default:
|
||||
slp = (struct curl_slist * *) paramp;
|
||||
if(*slp)
|
||||
if(!(*slp = slist_convert(ccsid, *slp, ASCII_CCSID)))
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,7 +772,7 @@ Curl_formadd_convert(struct curl_forms * forms,
|
||||
forms[formx].value = cp;
|
||||
|
||||
if(lengthx >= 0)
|
||||
forms[lengthx].value = (char *) l; /* Update to length after conversion. */
|
||||
forms[lengthx].value = (char *) l; /* Update length after conversion. */
|
||||
|
||||
return l;
|
||||
}
|
||||
@@ -1111,11 +1120,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
if(testwarn) {
|
||||
testwarn = 0;
|
||||
|
||||
#ifdef USE_TLS_SRP
|
||||
if((int) STRING_LAST != (int) STRING_TLSAUTH_PASSWORD + 1)
|
||||
#else
|
||||
if((int) STRING_LAST != (int) STRING_MAIL_AUTH + 1)
|
||||
#endif
|
||||
if((int) STRING_LAST != (int) STRING_BEARER + 1)
|
||||
curl_mfprintf(stderr,
|
||||
"*** 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_KEYPASSWD:
|
||||
case CURLOPT_KRBLEVEL:
|
||||
case CURLOPT_LOGIN_OPTIONS:
|
||||
case CURLOPT_MAIL_FROM:
|
||||
case CURLOPT_MAIL_AUTH:
|
||||
case CURLOPT_NETRC_FILE:
|
||||
@@ -1176,6 +1182,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
||||
case CURLOPT_USERAGENT:
|
||||
case CURLOPT_USERNAME:
|
||||
case CURLOPT_USERPWD:
|
||||
case CURLOPT_XOAUTH2_BEARER:
|
||||
s = va_arg(arg, char *);
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@ CURL_EXTERN char * curl_easy_unescape_ccsid(CURL * handle, const char * string,
|
||||
int length, int * outlength,
|
||||
unsigned int sccsid,
|
||||
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,
|
||||
unsigned int ccsid);
|
||||
CURL_EXTERN time_t curl_getdate_ccsid(const char * p, const time_t * unused,
|
||||
unsigned int ccsid);
|
||||
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,
|
||||
unsigned int ccsid);
|
||||
CURL_EXTERN const char * curl_share_strerror_ccsid(CURLSHcode error,
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
d c X'00004000'
|
||||
d CURL_VERSION_NTLM_WB...
|
||||
d c X'00008000'
|
||||
d CURL_VERSION_HTTP2...
|
||||
d c X'00010000'
|
||||
*
|
||||
d HTTPPOST_FILENAME...
|
||||
d c X'00000001'
|
||||
@@ -212,6 +214,8 @@
|
||||
d c 1
|
||||
d CURL_HTTP_VERSION_1_1...
|
||||
d c 2
|
||||
d CURL_HTTP_VERSION_2_0...
|
||||
d c 3
|
||||
*
|
||||
d CURL_NETRC_IGNORED...
|
||||
d c 0
|
||||
@@ -228,6 +232,12 @@
|
||||
d c 2
|
||||
d CURL_SSLVERSION_SSLv3...
|
||||
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 c 0
|
||||
@@ -1162,6 +1172,16 @@
|
||||
d c 00218
|
||||
d CURLOPT_XFERINFOFUNCTION...
|
||||
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)
|
||||
d CURLOPT_SSLKEYPASSWD...
|
||||
@@ -1329,10 +1349,35 @@
|
||||
d c X'00100029'
|
||||
d CURLINFO_LOCAL_PORT... CURLINFO_LONG + 42
|
||||
d c X'0020002A'
|
||||
d CURLINFO_TLS_SESSION... CURLINFO_SLIST + 43
|
||||
d c X'0040002B'
|
||||
*
|
||||
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
|
||||
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 s 10i 0 based(######ptr######) Enum
|
||||
d CURLCLOSEPOLICY_OLDEST...
|
||||
@@ -1451,7 +1496,9 @@
|
||||
d c 5
|
||||
d CURLM_UNKNOWN_OPTION...
|
||||
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_NONE c 0
|
||||
@@ -1560,12 +1607,7 @@
|
||||
d addrlen 10u 0
|
||||
d addr 16 struct sockaddr
|
||||
*
|
||||
d curl_khkey ds based(######ptr######)
|
||||
d qualified
|
||||
d key * const char *
|
||||
d len 10u 0
|
||||
d keytype 10i 0
|
||||
*
|
||||
d curl_khtype s 10i 0 based(######ptr######) enum
|
||||
d CURLKHTYPE_UNKNOWN...
|
||||
d c 0
|
||||
d CURLKHTYPE_RSA1...
|
||||
@@ -1575,6 +1617,12 @@
|
||||
d CURLKHTYPE_DSS...
|
||||
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 qualified
|
||||
d option like(CURLformoption)
|
||||
@@ -1622,6 +1670,12 @@
|
||||
d group * 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 qualified
|
||||
d filename * char *
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
setenv()
|
||||
|
||||
{
|
||||
# Define and export.
|
||||
|
||||
eval ${1}="${2}"
|
||||
export ${1}
|
||||
}
|
||||
|
||||
|
||||
case "${SCRIPTDIR}" in
|
||||
/*) ;;
|
||||
*) SCRIPTDIR="`pwd`/${SCRIPTDIR}"
|
||||
@@ -32,18 +42,23 @@ export SONAME
|
||||
#
|
||||
################################################################################
|
||||
|
||||
TARGETLIB='CURL' # Target OS/400 program library
|
||||
STATBNDDIR='CURL_A' # Static binding directory.
|
||||
DYNBNDDIR='CURL' # Dynamic binding directory.
|
||||
SRVPGM="CURL.${SONAME}" # Service program.
|
||||
TGTCCSID='500' # Target CCSID of objects
|
||||
DEBUG='*ALL' # Debug level
|
||||
OPTIMIZE='10' # Optimisation level
|
||||
OUTPUT='*NONE' # Compilation output option.
|
||||
TGTRLS='V5R3M0' # Target OS release
|
||||
setenv TARGETLIB 'CURL' # Target OS/400 program library.
|
||||
setenv STATBNDDIR 'CURL_A' # Static binding directory.
|
||||
setenv DYNBNDDIR 'CURL' # Dynamic binding directory.
|
||||
setenv SRVPGM "CURL.${SONAME}" # Service program.
|
||||
setenv TGTCCSID '500' # Target CCSID of objects.
|
||||
setenv DEBUG '*ALL' # Debug level.
|
||||
setenv OPTIMIZE '10' # Optimisation level
|
||||
setenv OUTPUT '*NONE' # Compilation output option.
|
||||
setenv TGTRLS 'V5R3M0' # Target OS release.
|
||||
setenv IFSDIR '/curl' # Installation IFS directory.
|
||||
|
||||
export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM TGTCCSID DEBUG OPTIMIZE OUTPUT
|
||||
export TGTRLS
|
||||
# Define ZLIB availability and locations.
|
||||
|
||||
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} INCDIR('/qibm/proddata/qadrt/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} OUTPUT(${OUTPUT})"
|
||||
CMD="${CMD} OPTIMIZE(${OPTIMIZE})"
|
||||
CMD="${CMD} DBGVIEW(${DEBUG})"
|
||||
|
||||
if [ "${3}" ]
|
||||
then CMD="${CMD} DEFINE(${3})"
|
||||
DEFINES="${3}"
|
||||
|
||||
if [ "${WITH_ZLIB}" != "0" ]
|
||||
then DEFINES="${DEFINES} HAVE_LIBZ HAVE_ZLIB_H"
|
||||
fi
|
||||
|
||||
if [ "${DEFINES}" ]
|
||||
then CMD="${CMD} DEFINE(${DEFINES})"
|
||||
fi
|
||||
|
||||
system "${CMD}"
|
||||
@@ -154,11 +181,17 @@ make_module()
|
||||
db2_name()
|
||||
|
||||
{
|
||||
basename "${1}" |
|
||||
if [ "${2}" = 'nomangle' ]
|
||||
then basename "${1}" |
|
||||
tr 'a-z-' 'A-Z_' |
|
||||
sed -e 's/\..*//' \
|
||||
-e 's/^\(.\).*\(.........\)$/\1\2/'
|
||||
else basename "${1}" |
|
||||
tr 'a-z-' 'A-Z_' |
|
||||
sed -e 's/\..*//' \
|
||||
-e 's/^CURL_*/C/' \
|
||||
-e 's/^\(.\).*\(.........\)$/\1\2/'
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/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}"`
|
||||
@@ -8,7 +8,7 @@ SCRIPTDIR=`dirname "${0}"`
|
||||
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
|
||||
then if action_needed curl/curlbuild.h curl/curlbuild.h.dist
|
||||
@@ -17,7 +17,7 @@ then if action_needed curl/curlbuild.h curl/curlbuild.h.dist
|
||||
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"
|
||||
|
||||
@@ -28,6 +28,15 @@ then CMD="CRTSRCPF FILE(${TARGETLIB}/H) RCDLEN(112)"
|
||||
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
|
||||
# integers.
|
||||
|
||||
@@ -48,16 +57,27 @@ copy_hfile()
|
||||
# Copy the header files.
|
||||
|
||||
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}"
|
||||
then copy_hfile "${DEST}" "${HFILE}"
|
||||
IFSDEST="${IFSINCLUDE}/`basename \"${HFILE}\"`"
|
||||
rm -f "${IFSDEST}"
|
||||
ln -s "${DEST}" "${IFSDEST}"
|
||||
fi
|
||||
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"
|
||||
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.
|
||||
|
||||
@@ -83,12 +83,12 @@ fi
|
||||
|
||||
# Gather the list of symbols to export.
|
||||
|
||||
EXPORTS=`grep '^CURL_EXTERN[ ]' \
|
||||
EXPORTS=`grep '^CURL_EXTERN[[:space:]]' \
|
||||
"${TOPDIR}"/include/curl/*.h \
|
||||
"${SCRIPTDIR}/ccsidcurl.h" |
|
||||
sed -e 's/^.*CURL_EXTERN[ ]\(.*\)(.*$/\1/' \
|
||||
-e 's/[ ]*$//' \
|
||||
-e 's/^.*[ ][ ]*//' \
|
||||
sed -e 's/^.*CURL_EXTERN[[:space:]]\(.*\)(.*$/\1/' \
|
||||
-e 's/[[:space:]]*$//' \
|
||||
-e 's/^.*[[:space:]][[:space:]]*//' \
|
||||
-e 's/^\*//' \
|
||||
-e 's/(\(.*\))/\1/'`
|
||||
|
||||
@@ -121,7 +121,11 @@ if [ "${LINK}" ]
|
||||
then CMD="CRTSRVPGM SRVPGM(${TARGETLIB}/${SRVPGM})"
|
||||
CMD="${CMD} SRCFILE(${TARGETLIB}/TOOLS) SRCMBR(BNDSRC)"
|
||||
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} TEXT('curl API library')"
|
||||
CMD="${CMD} TGTRLS(${TGTRLS})"
|
||||
|
||||
@@ -28,11 +28,11 @@ eval "`sed -e ': begin' \
|
||||
-e 's/\\\\\\n/ /' \
|
||||
-e 'b begin' \
|
||||
-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 ': keep' \
|
||||
-e 's/[ ]*=[ ]*/=/' \
|
||||
-e 's/=\\(.*[^ ]\\)[ ]*$/=\\"\\1\\"/' \
|
||||
-e 's/[[:space:]]*=[[:space:]]*/=/' \
|
||||
-e 's/=\\(.*[^[:space:]]\\)[[:space:]]*$/=\\"\\1\\"/' \
|
||||
-e 's/\\$(\\([^)]*\\))/${\\1}/g' \
|
||||
< Makefile.inc`"
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include <qadrt.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_QSOSSL
|
||||
#include <qsossl.h>
|
||||
#endif
|
||||
@@ -225,8 +229,7 @@ buffer_undef(localkey_t key, long size)
|
||||
if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */
|
||||
if(!pthread_key_create(&thdkey, thdbufdestroy))
|
||||
Curl_thread_buffer = buffer_threaded;
|
||||
else if (!(locbufs = calloc((size_t) LK_LAST,
|
||||
sizeof *locbufs))) {
|
||||
else if(!(locbufs = calloc((size_t) LK_LAST, sizeof *locbufs))) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
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
|
||||
Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
|
||||
char * nodename, curl_socklen_t nodenamelen,
|
||||
@@ -434,23 +459,8 @@ char *
|
||||
Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp)
|
||||
|
||||
{
|
||||
int i;
|
||||
char * cp;
|
||||
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;
|
||||
return set_thread_string(LK_SSL_ERROR,
|
||||
SSL_Strerror(sslreturnvalue, serrmsgp));
|
||||
}
|
||||
|
||||
#endif /* USE_QSOSSL */
|
||||
@@ -825,23 +835,7 @@ const char *
|
||||
Curl_gsk_strerror_a(int gsk_return_value)
|
||||
|
||||
{
|
||||
int i;
|
||||
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;
|
||||
return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
|
||||
}
|
||||
|
||||
int
|
||||
@@ -954,7 +948,8 @@ Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
|
||||
|
||||
|
||||
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_name_t target_name, gss_OID mech_type,
|
||||
gss_flags_t req_flags, OM_uint32 time_req,
|
||||
@@ -1224,8 +1219,8 @@ Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
|
||||
if(cp)
|
||||
free(cp);
|
||||
|
||||
/* Result data are binary in nature, so they haven't been converted to EBCDIC.
|
||||
Therefore do not convert. */
|
||||
/* Result data are binary in nature, so they haven't been
|
||||
converted to EBCDIC. Therefore do not convert. */
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1235,23 +1230,7 @@ char *
|
||||
Curl_ldap_err2string_a(int error)
|
||||
|
||||
{
|
||||
int i;
|
||||
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;
|
||||
return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
|
||||
}
|
||||
|
||||
|
||||
@@ -1492,3 +1471,79 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
|
||||
*addrlen = laddrlen;
|
||||
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
|
||||
|
||||
@@ -39,6 +39,8 @@ typedef enum {
|
||||
LK_EASY_STRERROR,
|
||||
LK_SHARE_STRERROR,
|
||||
LK_MULTI_STRERROR,
|
||||
LK_ZLIB_VERSION,
|
||||
LK_ZLIB_MSG,
|
||||
LK_LAST
|
||||
} localkey_t;
|
||||
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
/*
|
||||
** callback for CURLOPT_PROGRESSFUNCTION
|
||||
** callback for CURLOPT_XFERINFOFUNCTION
|
||||
*/
|
||||
|
||||
#define MAX_BARLENGTH 256
|
||||
|
||||
int tool_progress_cb(void *clientp,
|
||||
double dltotal, double dlnow,
|
||||
double ultotal, double ulnow)
|
||||
curl_off_t dltotal, curl_off_t dlnow,
|
||||
curl_off_t ultotal, curl_off_t ulnow)
|
||||
{
|
||||
/* The original progress-bar source code was written for curl by Lars Aas,
|
||||
and this new edition inherits some of his concepts. */
|
||||
@@ -60,10 +60,10 @@ int tool_progress_cb(void *clientp,
|
||||
return 0;
|
||||
|
||||
/* 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 */
|
||||
point = (curl_off_t)dlnow + (curl_off_t)ulnow + bar->initial_size;
|
||||
point = dlnow + ulnow + bar->initial_size;
|
||||
|
||||
if(point > total)
|
||||
/* we have got more than the expected total! */
|
||||
|
||||
@@ -43,8 +43,8 @@ void progressbarinit(struct ProgressData *bar,
|
||||
*/
|
||||
|
||||
int tool_progress_cb(void *clientp,
|
||||
double dltotal, double dlnow,
|
||||
double ultotal, double ulnow);
|
||||
curl_off_t dltotal, curl_off_t dlnow,
|
||||
curl_off_t ultotal, curl_off_t ulnow);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_CB_PRG_H */
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ struct Configurable {
|
||||
0 => -s is used to NOT show errors
|
||||
1 => -S has been used to show errors */
|
||||
char *userpwd;
|
||||
char *login_options;
|
||||
char *tls_username;
|
||||
char *tls_password;
|
||||
char *tls_authtype;
|
||||
|
||||
@@ -184,6 +184,9 @@ static const struct LongShort aliases[]= {
|
||||
{"01", "http1.1", FALSE},
|
||||
{"02", "http2.0", FALSE},
|
||||
{"1", "tlsv1", FALSE},
|
||||
{"10", "tlsv1.0", FALSE},
|
||||
{"11", "tlsv1.1", FALSE},
|
||||
{"12", "tlsv1.2", FALSE},
|
||||
{"2", "sslv2", FALSE},
|
||||
{"3", "sslv3", FALSE},
|
||||
{"4", "ipv4", FALSE},
|
||||
@@ -215,6 +218,7 @@ static const struct LongShort aliases[]= {
|
||||
{"El", "tlspassword", TRUE},
|
||||
{"Em", "tlsauthtype", TRUE},
|
||||
{"En", "ssl-allow-beast", FALSE},
|
||||
{"Eo", "login-options", TRUE},
|
||||
{"f", "fail", FALSE},
|
||||
{"F", "form", TRUE},
|
||||
{"Fs", "form-string", TRUE},
|
||||
@@ -1023,10 +1027,26 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '1':
|
||||
/* TLS version 1 */
|
||||
case '1': /* --tlsv1* options */
|
||||
switch(subletter) {
|
||||
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;
|
||||
case '2':
|
||||
/* SSL version 2 */
|
||||
config->ssl_version = CURL_SSLVERSION_SSLv2;
|
||||
@@ -1347,10 +1367,15 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
else
|
||||
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||
break;
|
||||
case 'n': /* no empty SSL fragments */
|
||||
case 'n': /* no empty SSL fragments, --ssl-allow-beast */
|
||||
if(curlinfo->features & CURL_VERSION_SSL)
|
||||
config->ssl_allow_beast = toggle;
|
||||
break;
|
||||
|
||||
case 'o': /* --login-options */
|
||||
GetStr(&config->login_options, nextarg);
|
||||
break;
|
||||
|
||||
default: /* certificate file */
|
||||
{
|
||||
char *certname, *passphrase;
|
||||
@@ -1668,7 +1693,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
/* user:password;options */
|
||||
/* user:password */
|
||||
GetStr(&config->userpwd, nextarg);
|
||||
cleanarg(nextarg);
|
||||
break;
|
||||
|
||||
@@ -120,7 +120,7 @@ static const char *const helptext[] = {
|
||||
" --libcurl FILE Dump libcurl equivalent code of this command line",
|
||||
#endif
|
||||
" --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",
|
||||
" -L, --location Follow redirects (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)",
|
||||
" --noproxy List of hosts which do not use proxy",
|
||||
" --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",
|
||||
" --pass PASS Pass phrase for the private key (SSL/SSH)",
|
||||
" --post301 "
|
||||
@@ -215,7 +215,8 @@ static const char *const helptext[] = {
|
||||
" -T, --upload-file FILE Transfer FILE to destination",
|
||||
" --url URL URL to work with",
|
||||
" -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",
|
||||
" --tlspassword STRING TLS password",
|
||||
" --tlsauthtype STRING TLS authentication type (default SRP)",
|
||||
|
||||
@@ -54,9 +54,7 @@
|
||||
# define MD5_CTX void *
|
||||
# define SHA_CTX void *
|
||||
# define SHA256_CTX void *
|
||||
# ifdef HAVE_NSS_INITCONTEXT
|
||||
static NSSInitContext *nss_context;
|
||||
# endif
|
||||
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
|
||||
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
|
||||
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
|
||||
@@ -240,7 +238,6 @@ static int nss_hash_init(void **pctx, SECOidTag hash_alg)
|
||||
PK11Context *ctx;
|
||||
|
||||
/* we have to initialize NSS if not initialized alraedy */
|
||||
#ifdef HAVE_NSS_INITCONTEXT
|
||||
if(!NSS_IsInitialized() && !nss_context) {
|
||||
static NSSInitParameters 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_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx = PK11_CreateDigestContext(hash_alg);
|
||||
if(!ctx)
|
||||
@@ -894,7 +890,7 @@ void clean_metalink(struct Configurable *config)
|
||||
|
||||
void metalink_cleanup(void)
|
||||
{
|
||||
#if defined(USE_NSS) && defined(HAVE_NSS_INITCONTEXT)
|
||||
#ifdef USE_NSS
|
||||
if(nss_context) {
|
||||
NSS_ShutdownContext(nss_context);
|
||||
nss_context = NULL;
|
||||
|
||||
@@ -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_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_RANGE, config->range);
|
||||
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) {
|
||||
/* we want the alternative style, then we have to implement it
|
||||
ourselves! */
|
||||
my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb);
|
||||
my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
|
||||
my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
|
||||
my_setopt(curl, CURLOPT_XFERINFODATA, &progressbar);
|
||||
}
|
||||
|
||||
/* new in libcurl 7.24.0: */
|
||||
|
||||
@@ -35,7 +35,10 @@
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
#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 char *my_get_line(FILE *fp);
|
||||
@@ -123,6 +126,7 @@ int parseconfig(const char *filename,
|
||||
char *param;
|
||||
int lineno = 0;
|
||||
bool alloced_param;
|
||||
bool dashed_option;
|
||||
|
||||
while(NULL != (aline = my_get_line(file))) {
|
||||
lineno++;
|
||||
@@ -146,7 +150,11 @@ int parseconfig(const char *filename,
|
||||
|
||||
/* the option keywords starts here */
|
||||
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++;
|
||||
/* ... and has ended here */
|
||||
|
||||
@@ -158,7 +166,7 @@ int parseconfig(const char *filename,
|
||||
#endif
|
||||
|
||||
/* pass spaces and separator(s) */
|
||||
while(*line && (ISSPACE(*line) || ISSEP(*line)))
|
||||
while(*line && (ISSPACE(*line) || ISSEP(*line, dashed_option)))
|
||||
line++;
|
||||
|
||||
/* the parameter starts here (unless quoted) */
|
||||
@@ -180,6 +188,24 @@ int parseconfig(const char *filename,
|
||||
while(*line && !ISSPACE(*line))
|
||||
line++;
|
||||
*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) {
|
||||
|
||||
@@ -78,6 +78,9 @@ const NameValue setopt_nv_CURL_SSLVERSION[] = {
|
||||
NV(CURL_SSLVERSION_TLSv1),
|
||||
NV(CURL_SSLVERSION_SSLv2),
|
||||
NV(CURL_SSLVERSION_SSLv3),
|
||||
NV(CURL_SSLVERSION_TLSv1_0),
|
||||
NV(CURL_SSLVERSION_TLSv1_1),
|
||||
NV(CURL_SSLVERSION_TLSv1_2),
|
||||
NVEND,
|
||||
};
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ typedef enum {
|
||||
|
||||
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];
|
||||
pat->type = UPTSet;
|
||||
@@ -48,17 +48,18 @@ static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount)
|
||||
pat->content.Set.ptr_s = 0;
|
||||
pat->globindex = -1;
|
||||
|
||||
(*amount)++;
|
||||
|
||||
pat->content.Set.elements = malloc(sizeof(char*));
|
||||
|
||||
if(!pat->content.Set.elements)
|
||||
return GLOBERROR("out of memory", 0, GLOB_NO_MEM);
|
||||
|
||||
pat->content.Set.elements[0] = strdup(glob->glob_buffer);
|
||||
pat->content.Set.elements[0] = malloc(len+1);
|
||||
if(!pat->content.Set.elements[0])
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -211,7 +212,7 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
|
||||
}
|
||||
}
|
||||
else
|
||||
pattern+=3;
|
||||
pattern += 4;
|
||||
|
||||
*posp += (pattern - *patternp);
|
||||
|
||||
@@ -307,11 +308,13 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
|
||||
/* processes a literal string component of a URL
|
||||
special characters '{' and '[' branch to set/range processing functions
|
||||
*/
|
||||
char* buf = glob->glob_buffer;
|
||||
GlobCode res = GLOB_OK;
|
||||
int globindex = 0; /* count "actual" globs */
|
||||
|
||||
*amount = 1;
|
||||
|
||||
while(*pattern && !res) {
|
||||
char *buf = glob->glob_buffer;
|
||||
int sublen = 0;
|
||||
while(*pattern && *pattern != '{' && *pattern != '[') {
|
||||
if(*pattern == '}' || *pattern == ']')
|
||||
@@ -333,12 +336,9 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
|
||||
if(sublen) {
|
||||
/* we got a literal string, add it as a single-item list */
|
||||
*buf = '\0';
|
||||
res = glob_fixed(glob, amount);
|
||||
res = glob_fixed(glob, glob->glob_buffer, sublen);
|
||||
}
|
||||
else {
|
||||
if(!*amount)
|
||||
*amount = 1;
|
||||
|
||||
switch (*pattern) {
|
||||
case '\0': /* done */
|
||||
break;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# per line.
|
||||
# Lines starting with '#' letters are treated as comments.
|
||||
594
|
||||
815
|
||||
816
|
||||
1209
|
||||
1211
|
||||
1512
|
||||
|
||||
@@ -64,14 +64,19 @@ test700 test701 test702 test703 test704 test705 test706 test707 test708 \
|
||||
test709 test710 test711 test712 \
|
||||
\
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
|
||||
@@ -96,12 +101,12 @@ test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
|
||||
test1216 test1217 test1218 test1219 \
|
||||
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
|
||||
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
|
||||
test1236 test1237 test1238 test1239 \
|
||||
test1236 test1237 test1238 test1239 test1240 \
|
||||
\
|
||||
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
|
||||
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
|
||||
test1316 test1317 test1318 test1319 test1320 test1321 test1322 test1323 \
|
||||
test1324 test1325 test1326 test1327 test1328 test1329 test1330 test1331 \
|
||||
test1316 test1317 test1318 test1319 test1320 test1321 \
|
||||
test1325 test1326 test1327 test1328 test1329 test1330 test1331 \
|
||||
test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 \
|
||||
test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 \
|
||||
test1348 test1349 test1350 test1351 test1352 test1353 test1354 test1355 \
|
||||
|
||||
48
tests/data/test1240
Normal file
48
tests/data/test1240
Normal 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>
|
||||
@@ -27,7 +27,7 @@ imap
|
||||
IMAP doesn't perform SELECT if re-using the same mailbox
|
||||
</name>
|
||||
<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>
|
||||
</client>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user