Compare commits
296 Commits
curl-7_35_
...
curl-7_36_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f041c9d6e | ||
|
|
4d06b27921 | ||
|
|
965690f67e | ||
|
|
5019c78095 | ||
|
|
517b06d657 | ||
|
|
e798e6759b | ||
|
|
b877494a27 | ||
|
|
3ebfaf6a03 | ||
|
|
ed02f0abca | ||
|
|
5e097583f7 | ||
|
|
196140dcaf | ||
|
|
4ff71183b9 | ||
|
|
2fc31dcf74 | ||
|
|
715125e790 | ||
|
|
930b81387b | ||
|
|
ec0079a99d | ||
|
|
47f8e99e78 | ||
|
|
ff25f437a5 | ||
|
|
31265376bc | ||
|
|
7a1fb8e816 | ||
|
|
5017d5ada8 | ||
|
|
4d6108315b | ||
|
|
67061e3f4e | ||
|
|
c864d81289 | ||
|
|
b4f6cd46eb | ||
|
|
4c599b9d2d | ||
|
|
c03243576a | ||
|
|
02bba0ce7d | ||
|
|
e8aff0c588 | ||
|
|
9b5b6a2b1a | ||
|
|
ca7d1de69c | ||
|
|
61591eee68 | ||
|
|
596800378d | ||
|
|
8c4d6ceec0 | ||
|
|
891ef341b3 | ||
|
|
2465ee7573 | ||
|
|
9787b8e9d4 | ||
|
|
dcdbac2568 | ||
|
|
ac7118319e | ||
|
|
8ddda0e999 | ||
|
|
74ad0221cc | ||
|
|
a55e7f0abd | ||
|
|
63e3e03dae | ||
|
|
6da4085e48 | ||
|
|
e591165f94 | ||
|
|
e84d0b41f6 | ||
|
|
539412851c | ||
|
|
219a0fbe76 | ||
|
|
0b3750b5c2 | ||
|
|
a21c04f391 | ||
|
|
c01467b753 | ||
|
|
778e4bb276 | ||
|
|
9cb7802cfd | ||
|
|
6f416fa462 | ||
|
|
420d9ff3eb | ||
|
|
85484355b3 | ||
|
|
d8073db304 | ||
|
|
7fef4016de | ||
|
|
68920b6c11 | ||
|
|
46b1d0a047 | ||
|
|
eba197161a | ||
|
|
36802d6e0c | ||
|
|
f1a9e6858e | ||
|
|
75e996f29f | ||
|
|
5513bbd5c3 | ||
|
|
1f07718123 | ||
|
|
cde0cf7c5e | ||
|
|
53f1f4a18e | ||
|
|
bd248a0b80 | ||
|
|
219d19a401 | ||
|
|
78f26394dc | ||
|
|
4efa1d29e2 | ||
|
|
fd97c17bb7 | ||
|
|
5577540ad5 | ||
|
|
17df2d8f8e | ||
|
|
fc59a9e18f | ||
|
|
07d7603b45 | ||
|
|
1a9b58fcb2 | ||
|
|
3228deff40 | ||
|
|
e9665e9658 | ||
|
|
d48eb1dd69 | ||
|
|
4548e0fe71 | ||
|
|
70052836d1 | ||
|
|
249dc83571 | ||
|
|
0704dd770d | ||
|
|
ad388a7d37 | ||
|
|
87683d4b76 | ||
|
|
f35668985e | ||
|
|
e904b15f21 | ||
|
|
63fc8ee7be | ||
|
|
c27cc68815 | ||
|
|
0af2322bc6 | ||
|
|
59b5ef444e | ||
|
|
afc6e5004f | ||
|
|
0d9ddf91ca | ||
|
|
cc31a4a645 | ||
|
|
665096e24c | ||
|
|
d6b9f054e9 | ||
|
|
2249f7fe70 | ||
|
|
705a4cb549 | ||
|
|
6512e93be1 | ||
|
|
3674f2021d | ||
|
|
8c80840d01 | ||
|
|
24e22e1078 | ||
|
|
c10bf9bb36 | ||
|
|
e6e8b14405 | ||
|
|
b914e7ed02 | ||
|
|
ee23d13a79 | ||
|
|
dcbae71812 | ||
|
|
67f051051f | ||
|
|
b98c74b67e | ||
|
|
6969e24aee | ||
|
|
e08d0662b7 | ||
|
|
b5486adc9b | ||
|
|
a660c0dbe6 | ||
|
|
3521e4e40d | ||
|
|
873178a657 | ||
|
|
647f83e809 | ||
|
|
0d6225ad0d | ||
|
|
8749bbe7fd | ||
|
|
03c288202e | ||
|
|
938f93549f | ||
|
|
911a5c3646 | ||
|
|
f207f7e427 | ||
|
|
b1096d2352 | ||
|
|
452a4d90a4 | ||
|
|
860424bb06 | ||
|
|
035b91a26c | ||
|
|
e9dfdef411 | ||
|
|
854aca5420 | ||
|
|
4b4e8a5853 | ||
|
|
184c3e2d37 | ||
|
|
b04c158adf | ||
|
|
2111c2ed07 | ||
|
|
1f60728f81 | ||
|
|
0d94640c9b | ||
|
|
575a2b684b | ||
|
|
86f266b004 | ||
|
|
79a9f8c942 | ||
|
|
d765099813 | ||
|
|
f3bae6ed73 | ||
|
|
013e9a11ff | ||
|
|
77a51364a4 | ||
|
|
6239146e93 | ||
|
|
dc0f8c04ec | ||
|
|
2de045ff7c | ||
|
|
f80ca7a05a | ||
|
|
89070d0e68 | ||
|
|
779afe3bbf | ||
|
|
f3ce1af9fc | ||
|
|
3c2c1f9876 | ||
|
|
8451623b45 | ||
|
|
0a568867c0 | ||
|
|
91c13d759a | ||
|
|
89c29aa70f | ||
|
|
75f00de55c | ||
|
|
69745aaa45 | ||
|
|
01844658df | ||
|
|
38a56a9d94 | ||
|
|
25600bdf75 | ||
|
|
1813a77b02 | ||
|
|
d3d871cb4f | ||
|
|
db981b7b30 | ||
|
|
378af08c99 | ||
|
|
c021a60bcc | ||
|
|
bcb32e915e | ||
|
|
0ab97ba009 | ||
|
|
bff7398942 | ||
|
|
ec9476052d | ||
|
|
8f5a9147be | ||
|
|
82a4d537c3 | ||
|
|
87e873c6d0 | ||
|
|
33224f9bcd | ||
|
|
c8d1733d12 | ||
|
|
3a0d1bebba | ||
|
|
909a68c121 | ||
|
|
70bd9784de | ||
|
|
daa182afa6 | ||
|
|
230e872dbd | ||
|
|
5a997d97fd | ||
|
|
1861a1de67 | ||
|
|
86a40f5d1a | ||
|
|
ae363075e6 | ||
|
|
ea3828e0c7 | ||
|
|
cc0da321de | ||
|
|
8e62f7a650 | ||
|
|
8cf63f88c2 | ||
|
|
c5f8e2f5f4 | ||
|
|
6374ab2a36 | ||
|
|
6b9a3c1865 | ||
|
|
1f148c103c | ||
|
|
132f5edfbd | ||
|
|
2d8623e85d | ||
|
|
85a4df8b79 | ||
|
|
e2dae8a7c2 | ||
|
|
a3a6b03c30 | ||
|
|
3b929b6a65 | ||
|
|
67d14ab98f | ||
|
|
6c492f34e5 | ||
|
|
fa8d7ce4fe | ||
|
|
09d907ee68 | ||
|
|
f3a12460ad | ||
|
|
9597f7dfbc | ||
|
|
7969a77735 | ||
|
|
4a8c877273 | ||
|
|
265f2e9ed7 | ||
|
|
1ebf22cc0e | ||
|
|
ff92fcfb90 | ||
|
|
8d1377282e | ||
|
|
1505e4612b | ||
|
|
b93755df37 | ||
|
|
d10065c05a | ||
|
|
456169f9e5 | ||
|
|
dd97828df7 | ||
|
|
5204b45ff9 | ||
|
|
225ec4312f | ||
|
|
18b540f9d1 | ||
|
|
f8abd56450 | ||
|
|
61ba1daba0 | ||
|
|
06b4275c0d | ||
|
|
133cdd29ea | ||
|
|
ff0547e70e | ||
|
|
7d242658ac | ||
|
|
dde3081085 | ||
|
|
2dc7ad23fd | ||
|
|
e5524b7b25 | ||
|
|
0ea9f70049 | ||
|
|
4082dc9de6 | ||
|
|
dbccf497da | ||
|
|
63b26d889f | ||
|
|
4d8db595ca | ||
|
|
6127e54f40 | ||
|
|
8b6654224b | ||
|
|
c35d05aa62 | ||
|
|
8034b08e0e | ||
|
|
b811200f64 | ||
|
|
c1daf6c0cd | ||
|
|
cf80b85b66 | ||
|
|
2f89a61cc0 | ||
|
|
0104678c79 | ||
|
|
ffb8a21d85 | ||
|
|
9ab0dc618f | ||
|
|
83dbd06936 | ||
|
|
e5acae0052 | ||
|
|
efc112079c | ||
|
|
2c49f2e3db | ||
|
|
9f42205dcc | ||
|
|
4ea2d5579b | ||
|
|
9f132f9f39 | ||
|
|
ca9ab24ed5 | ||
|
|
480ca49ecb | ||
|
|
82f558366f | ||
|
|
6fb34ea6c6 | ||
|
|
a738bb1c9f | ||
|
|
0f213fdca1 | ||
|
|
be9cc620b5 | ||
|
|
c631a54bb6 | ||
|
|
768151449b | ||
|
|
97857de80e | ||
|
|
784f225266 | ||
|
|
b58b87e76e | ||
|
|
48c3bed43b | ||
|
|
1c9aaa0bac | ||
|
|
c5165b8458 | ||
|
|
88705ef80e | ||
|
|
0952c9abcc | ||
|
|
83f52a455f | ||
|
|
a7affd637f | ||
|
|
93f473c78a | ||
|
|
a878cb3056 | ||
|
|
0e11307057 | ||
|
|
0f23662af7 | ||
|
|
dd011df9e1 | ||
|
|
8e778887b5 | ||
|
|
99b4ff8b6f | ||
|
|
22c198fa89 | ||
|
|
c3fe3d9926 | ||
|
|
62e3d66cc6 | ||
|
|
b451c10d1e | ||
|
|
be84524cc2 | ||
|
|
803581d3e0 | ||
|
|
341d09bc2b | ||
|
|
0070f7a09d | ||
|
|
220bcba93d | ||
|
|
eb91e1a58f | ||
|
|
2319221c83 | ||
|
|
914b60c827 | ||
|
|
07b66cbfa4 | ||
|
|
86724581b6 | ||
|
|
665c160f0a | ||
|
|
e15e73b741 | ||
|
|
53940f8834 | ||
|
|
8d3608f2ad | ||
|
|
8bcf677a30 | ||
|
|
5e7fe58698 | ||
|
|
c3678f3bf6 |
183
RELEASE-NOTES
183
RELEASE-NOTES
@@ -1,68 +1,86 @@
|
||||
Curl and libcurl 7.35.0
|
||||
Curl and libcurl 7.36.0
|
||||
|
||||
Public curl releases: 137
|
||||
Public curl releases: 138
|
||||
Command line options: 161
|
||||
curl_easy_setopt() options: 206
|
||||
Public functions in libcurl: 58
|
||||
Known libcurl bindings: 42
|
||||
Contributors: 1104
|
||||
Contributors: 1123
|
||||
|
||||
This release includes the following SECURITY ADVISORIES:
|
||||
|
||||
o wrong re-use of connections [16]
|
||||
o IP address wildcard certificate validation [17]
|
||||
o not verifying certs for TLS to IP address / Darwinssl [18]
|
||||
o not verifying certs for TLS to IP address / Winssl [19]
|
||||
|
||||
This release includes the following changes:
|
||||
|
||||
o imap/pop3/smtp: Added support for SASL authentication downgrades
|
||||
o imap/pop3/smtp: Extended the login options to support multiple auth mechanisms
|
||||
o TheArtOfHttpScripting: major update, converted layout and more
|
||||
o mprintf: Added support for I, I32 and I64 size specifiers
|
||||
o makefile: Added support for VC7, VC11 and VC12
|
||||
o ntlm: Added support for NTLMv2 [2]
|
||||
o tool: Added support for URL specific options [3]
|
||||
o openssl: add ALPN support
|
||||
o gtls: add ALPN support
|
||||
o nss: add ALPN and NPN support
|
||||
o added CURLOPT_EXPECT_100_TIMEOUT_MS [7]
|
||||
o tool: add --no-alpn and --no-npn
|
||||
o added CURLOPT_SSL_ENABLE_NPN and CURLOPT_SSL_ENABLE_ALPN
|
||||
o winssl: enable TLSv1.1 and TLSv1.2 by default
|
||||
o winssl: TLSv1.2 disables certificate signatures using MD5 hash
|
||||
o winssl: enable hostname verification of IP address using SAN or CN [11]
|
||||
o darwinssl: Don't omit CN verification when an IP address is used [12]
|
||||
o http2: build with current nghttp2 version
|
||||
o polarssl: dropped support for PolarSSL < 1.3.0
|
||||
o openssl: info message with SSL version used
|
||||
|
||||
This release includes the following bugfixes:
|
||||
|
||||
o SECURITY ADVISORY: re-use of wrong HTTP NTLM connection [25]
|
||||
|
||||
o curl_easy_setopt: Fixed OAuth 2.0 Bearer option name [1]
|
||||
o pop3: Fixed APOP being determined by CAPA response rather than by timestamp
|
||||
o Curl_pp_readresp: zero terminate line [2]
|
||||
o FILE: don't wait due to CURLOPT_MAX_RECV_SPEED_LARGE [3]
|
||||
o docs: mention CURLOPT_MAX_RECV/SEND_SPEED_LARGE don't work for FILE://
|
||||
o pop3: Fixed auth preference not being honored when CAPA not supported
|
||||
o imap: Fixed auth preference not being honored when CAPABILITY not supported
|
||||
o threaded resolver: Use pthread_t * for curl_thread_t [4]
|
||||
o FILE: we don't support paused transfers using this protocol [5]
|
||||
o connect: Try all addresses in first connection attempt [6]
|
||||
o curl_easy_setopt.3: Added SMTP information to CURLOPT_INFILESIZE_LARGE
|
||||
o OpenSSL: Fix forcing SSLv3 connections [7]
|
||||
o openssl: allow explicit sslv2 selection [8]
|
||||
o FTP parselist: fix "total" parser [9]
|
||||
o conncache: fix possible dereference of null pointer
|
||||
o multi.c: fix possible dereference of null pointer
|
||||
o mk-ca-bundle: introduces -d and warns about using this script
|
||||
o ConnectionExists: fix NTLM check for new connection [10]
|
||||
o trynextip: fix build for non-IPV6 capable systems [11]
|
||||
o Curl_updateconninfo: don't do anything for UDP "connections" [12]
|
||||
o darwinssl: un-break Leopard build after PKCS#12 change [13]
|
||||
o threaded-resolver: never use NULL hints with getaddrinf [14]
|
||||
o multi_socket: remind app if timeout didn't run
|
||||
o OpenSSL: deselect weak ciphers by default [15]
|
||||
o error message: Sensible message on timeout when transfer size unknown [16]
|
||||
o curl_easy_setopt.3: mention how to unset CURLOPT_INFILESIZE*
|
||||
o win32: Fixed use of deprecated function 'GetVersionInfoEx' for VC12 [17]
|
||||
o configure: fix gssapi linking on HP-UX [18]
|
||||
o chunked-parser: abort on overflows, allow 64 bit chunks
|
||||
o chunked parsing: relax the CR strictness [19]
|
||||
o cookie: max-age fixes [20]
|
||||
o progress bar: always update when at 100%
|
||||
o progress bar: increase update frequency to 10Hz
|
||||
o tool: Fixed incorrect return code if command line parser runs out of memory
|
||||
o tool: Fixed incorrect return code if password prompting runs out of memory
|
||||
o HTTP POST: omit Content-Length if data size is unknown [21]
|
||||
o GnuTLS: disable insecure ciphers
|
||||
o GnuTLS: honor --slv2 and the --tlsv1[.N] switches
|
||||
o multi: Fixed a memory leak on OOM condition
|
||||
o netrc: Fixed a memory and file descriptor leak on OOM
|
||||
o getpass: fix password parsing from console [22]
|
||||
o TFTP: fix crash on time-out [23]
|
||||
o hostip: don't remove DNS entries that are in use [24]
|
||||
o tests: lots of tests fixed to pass the OOM torture tests
|
||||
o nss: allow to use ECC ciphers if NSS implements them [1]
|
||||
o netrc: Fixed a memory leak in an OOM condition
|
||||
o ftp: fixed a memory leak on wildcard error path
|
||||
o pipeline: Fixed a NULL pointer dereference on OOM
|
||||
o nss: prefer highest available TLS version
|
||||
o 100-continue: fix timeout condition [4]
|
||||
o ssh: Fixed a NULL pointer dereference on OOM condition
|
||||
o formpost: use semicolon in multipart/mixed [5]
|
||||
o --help: add missing --tlsv1.x options
|
||||
o formdata: Fixed memory leak on OOM condition
|
||||
o ConnectionExists: reusing possible HTTP+NTLM connections better [6]
|
||||
o mingw32: fix compilation
|
||||
o chunked decoder: track overflows correctly [8]
|
||||
o curl_easy_setopt.3: add CURL_HTTP_VERSION_2_0
|
||||
o dict: fix memory leak in OOM exit path
|
||||
o valgrind: added suppression on optimized code
|
||||
o curl: output protocol headers using binary mode
|
||||
o tool: Added URL index to password prompt for multiple operations
|
||||
o ConnectionExists: re-use non-NTLM connections better [9]
|
||||
o axtls: call ssl_read repeatedly
|
||||
o multi: make MAXCONNECTS default 4 x number of easy handles function
|
||||
o configure: Fix the --disable-crypto-auth option
|
||||
o multi: ignore SIGPIPE internally
|
||||
o curl.1: update the description of --tlsv1
|
||||
o SFTP: skip reading the dir when NOBODY=1 [10]
|
||||
o easy: Fixed a memory leak on OOM condition
|
||||
o tool: Fixed incorrect return code when setting HTTP request fails
|
||||
o configure: Tiny fix to honor POSIX
|
||||
o tool: Do not output libcurl source for the information only parameters
|
||||
o Rework Open Watcom make files to use standard Wmake features
|
||||
o x509asn: moved out Curl_verifyhost from NSS builds
|
||||
o configure: call it GSS-API
|
||||
o hostcheck: Curl_cert_hostcheck is not used by NSS builds
|
||||
o multi_runsingle: move timestamp into INIT [13]
|
||||
o remote_port: allow connect to port 0
|
||||
o parse_remote_port: error out on illegal port numbers better
|
||||
o ssh: Pass errors from libssh2_sftp_read up the stack
|
||||
o docs: remove documentation on setting up krb4 support
|
||||
o polarssl: build fixes to work with PolarSSL 1.3.x
|
||||
o polarssl: fix possible handshake timeout issue in multi
|
||||
o nss: allow to enable/disable cipher-suites better
|
||||
o ssh: prevent a logic error that could result in an infinite loop
|
||||
o http2: free resources on disconnect
|
||||
o polarssl: avoid extra newlines in debug messages
|
||||
o rtsp: parse "Session:" header properly [14]
|
||||
o trynextip: don't store 'ai' on failed connects
|
||||
o Curl_cert_hostcheck: strip trailing dots in host name and wildcard
|
||||
|
||||
This release includes the following known bugs:
|
||||
|
||||
@@ -71,40 +89,33 @@ 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:
|
||||
|
||||
Abram Pousada, Barry Abrahamson, Björn Stenberg, Cédric Deltheil, Chen Prog,
|
||||
Christian Weisgerber, Colin Hogben, Dan Fandrich, Daniel Stenberg,
|
||||
Fabian Frank, Glenn Sheridan, Guenter Knauf, He Qin, Iida Yosiaki,
|
||||
Jeff Hodges, Justin Maggard, Leif W, Luke Dashjr, Maks Naumov, Marc Hoersken,
|
||||
Michael Osipov, Michal Górny and Anthony G. Basile, Mohammad AlSaleh,
|
||||
Nick Zitzmann, Paras Sethia, Petr Novak, Priyanka Shah, Romulo A. Ceccon,
|
||||
Steve Holme, Tobias Markus, Viktor Szakáts, Yehezkel Horowitz, Yingwei Liu
|
||||
Adam Sampson, Arvid Norberg, Brad Spencer, Colin Hogben, Dan Fandrich,
|
||||
Daniel Stenberg, David Ryskalczyk, Fabian Frank, Gaël PORTAY, Gisle Vanem,
|
||||
Hubert Kario, Jeff King, Jiri Malak, Kamil Dudka, Maks Naumov, Marc Hoersken,
|
||||
Michael Osipov, Mike Hasselberg, Nick Zitzmann, Patrick Monnerat, Prash Dush,
|
||||
Remi Gacogne, Rob Davies, Romulo A. Ceccon, Shao Shuchao, Steve Holme,
|
||||
Tatsuhiro Tsujikawa, Thomas Braun, Tiit Pikma, Yehezkel Horowitz,
|
||||
|
||||
Thanks! (and sorry if I forgot to mention someone)
|
||||
|
||||
References to bug reports and discussions on issues:
|
||||
|
||||
[1] = http://curl.haxx.se/bug/view.cgi?id=1313
|
||||
[2] = http://curl.haxx.se/mail/lib-2013-12/0113.html
|
||||
[3] = http://curl.haxx.se/bug/view.cgi?id=1312
|
||||
[4] = http://curl.haxx.se/bug/view.cgi?id=1314
|
||||
[5] = http://curl.haxx.se/bug/view.cgi?id=1286
|
||||
[6] = http://curl.haxx.se/bug/view.cgi?id=1315
|
||||
[7] = http://curl.haxx.se/mail/lib-2014-01/0002.html
|
||||
[8] = http://curl.haxx.se/mail/lib-2014-01/0013.html
|
||||
[9] = http://curl.haxx.se/mail/lib-2014-01/0019.html
|
||||
[10] = http://curl.haxx.se/mail/lib-2014-01/0046.html
|
||||
[11] = http://curl.haxx.se/bug/view.cgi?id=1322
|
||||
[12] = http://curl.haxx.se/mail/archive-2014-01/0016.html
|
||||
[13] = http://curl.haxx.se/mail/lib-2013-12/0150.html
|
||||
[14] = http://curl.haxx.se/mail/lib-2014-01/0061.html
|
||||
[15] = http://curl.haxx.se/bug/view.cgi?id=1323
|
||||
[16] = http://curl.haxx.se/mail/lib-2014-01/0115.html
|
||||
[17] = http://curl.haxx.se/mail/lib-2014-01/0134.html
|
||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1321
|
||||
[19] = http://curl.haxx.se/mail/archive-2014-01/0000.html
|
||||
[20] = http://curl.haxx.se/mail/lib-2014-01/0130.html
|
||||
[21] = http://curl.haxx.se/mail/lib-2014-01/0103.html
|
||||
[22] = https://github.com/bagder/curl/pull/87
|
||||
[23] = http://curl.haxx.se/mail/lib-2014-01/0246.html
|
||||
[24] = http://curl.haxx.se/bug/view.cgi?id=1327
|
||||
[25] = http://curl.haxx.se/docs/adv_20140129.html
|
||||
[1] = https://bugzilla.redhat.com/1058776
|
||||
[2] = http://curl.haxx.se/mail/lib-2014-01/0183.html
|
||||
[3] = http://curl.haxx.se/mail/archive-2013-11/0006.html
|
||||
[4] = http://curl.haxx.se/bug/view.cgi?id=1334
|
||||
[5] = http://curl.haxx.se/bug/view.cgi?id=1333
|
||||
[6] = http://curl.haxx.se/mail/lib-2014-02/0100.html
|
||||
[7] = http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTEXPECT100TIMEOUTMS
|
||||
[8] = http://curl.haxx.se/mail/lib-2014-02/0097.html
|
||||
[9] = http://thread.gmane.org/gmane.comp.version-control.git/242213
|
||||
[10] = http://curl.haxx.se/mail/lib-2014-02/0155.html
|
||||
[11] = http://curl.haxx.se/mail/lib-2014-02/0243.html
|
||||
[12] = https://github.com/bagder/curl/pull/93
|
||||
[13] = http://curl.haxx.se/mail/lib-2014-02/0036.html
|
||||
[14] = http://curl.haxx.se/mail/lib-2014-03/0134.html
|
||||
[15] = http://curl.haxx.se/bug/view.cgi?id=1337
|
||||
[16] = http://curl.haxx.se/docs/adv_20140326A.html
|
||||
[17] = http://curl.haxx.se/docs/adv_20140326B.html
|
||||
[18] = http://curl.haxx.se/docs/adv_20140326C.html
|
||||
[19] = http://curl.haxx.se/docs/adv_20140326D.html
|
||||
|
||||
53
configure.ac
53
configure.ac
@@ -1173,26 +1173,26 @@ dnl **********************************************************************
|
||||
dnl Check for GSS-API libraries
|
||||
dnl **********************************************************************
|
||||
|
||||
dnl check for gss stuff in the /usr as default
|
||||
dnl check for GSS-API stuff in the /usr as default
|
||||
|
||||
GSSAPI_ROOT="/usr"
|
||||
AC_ARG_WITH(gssapi-includes,
|
||||
AC_HELP_STRING([--with-gssapi-includes=DIR],
|
||||
[Specify location of GSSAPI header]),
|
||||
[Specify location of GSS-API headers]),
|
||||
[ GSSAPI_INCS="-I$withval"
|
||||
want_gss="yes" ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(gssapi-libs,
|
||||
AC_HELP_STRING([--with-gssapi-libs=DIR],
|
||||
[Specify location of GSSAPI libs]),
|
||||
[Specify location of GSS-API libs]),
|
||||
[ GSSAPI_LIB_DIR="-L$withval"
|
||||
want_gss="yes" ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(gssapi,
|
||||
AC_HELP_STRING([--with-gssapi=DIR],
|
||||
[Where to look for GSSAPI]), [
|
||||
[Where to look for GSS-API]), [
|
||||
GSSAPI_ROOT="$withval"
|
||||
if test x"$GSSAPI_ROOT" != xno; then
|
||||
want_gss="yes"
|
||||
@@ -1204,7 +1204,7 @@ AC_ARG_WITH(gssapi,
|
||||
])
|
||||
|
||||
save_CPPFLAGS="$CPPFLAGS"
|
||||
AC_MSG_CHECKING([if GSSAPI support is requested])
|
||||
AC_MSG_CHECKING([if GSS-API support is requested])
|
||||
if test x"$want_gss" = xyes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
|
||||
@@ -1221,7 +1221,7 @@ if test x"$want_gss" = xyes; then
|
||||
AC_CHECK_HEADER(gss.h,
|
||||
[
|
||||
dnl found in the given dirs
|
||||
AC_DEFINE(HAVE_GSSGNU, 1, [if you have the GNU gssapi libraries])
|
||||
AC_DEFINE(HAVE_GSSGNU, 1, [if you have GNU GSS])
|
||||
gnu_gss=yes
|
||||
],
|
||||
[
|
||||
@@ -1242,19 +1242,19 @@ AC_INCLUDES_DEFAULT
|
||||
AC_CHECK_HEADER(gssapi.h,
|
||||
[
|
||||
dnl found
|
||||
AC_DEFINE(HAVE_GSSHEIMDAL, 1, [if you have the Heimdal gssapi libraries])
|
||||
AC_DEFINE(HAVE_GSSHEIMDAL, 1, [if you have Heimdal])
|
||||
],
|
||||
[
|
||||
dnl no header found, disabling GSS
|
||||
want_gss=no
|
||||
AC_MSG_WARN(disabling GSSAPI since no header files was found)
|
||||
AC_MSG_WARN(disabling GSS-API support since no header files were found)
|
||||
]
|
||||
)
|
||||
else
|
||||
dnl MIT found
|
||||
AC_DEFINE(HAVE_GSSMIT, 1, [if you have the MIT gssapi libraries])
|
||||
dnl check if we have a really old MIT kerberos (<= 1.2)
|
||||
AC_MSG_CHECKING([if gssapi headers declare GSS_C_NT_HOSTBASED_SERVICE])
|
||||
AC_DEFINE(HAVE_GSSMIT, 1, [if you have MIT Kerberos])
|
||||
dnl check if we have a really old MIT Kerberos version (<= 1.2)
|
||||
AC_MSG_CHECKING([if GSS-API headers declare GSS_C_NT_HOSTBASED_SERVICE])
|
||||
AC_COMPILE_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
#include <gssapi/gssapi.h>
|
||||
@@ -1272,7 +1272,7 @@ AC_INCLUDES_DEFAULT
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
AC_DEFINE(HAVE_OLD_GSSMIT, 1,
|
||||
[if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE])
|
||||
[if you have an old MIT Kerberos version, lacking GSS_C_NT_HOSTBASED_SERVICE])
|
||||
])
|
||||
fi
|
||||
]
|
||||
@@ -1281,9 +1281,9 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
if test x"$want_gss" = xyes; then
|
||||
AC_DEFINE(HAVE_GSSAPI, 1, [if you have the gssapi libraries])
|
||||
AC_DEFINE(HAVE_GSSAPI, 1, [if you have GSS-API libraries])
|
||||
|
||||
curl_gss_msg="enabled (MIT/Heimdal)"
|
||||
curl_gss_msg="enabled (MIT Kerberos/Heimdal)"
|
||||
|
||||
if test -n "$gnu_gss"; then
|
||||
curl_gss_msg="enabled (GNU GSS)"
|
||||
@@ -1594,7 +1594,10 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
|
||||
ENGINE_cleanup \
|
||||
CRYPTO_cleanup_all_ex_data \
|
||||
SSL_get_shutdown \
|
||||
SSLv2_client_method )
|
||||
SSLv2_client_method \
|
||||
SSL_CTX_set_next_proto_select_cb \
|
||||
SSL_CTX_set_alpn_protos \
|
||||
SSL_CTX_set_alpn_select_cb )
|
||||
|
||||
dnl Make an attempt to detect if this is actually yassl's headers and
|
||||
dnl OpenSSL emulation layer. We still leave everything else believing
|
||||
@@ -2466,19 +2469,19 @@ AC_HELP_STRING([--disable-versioned-symbols], [Disable versioned symbols in shar
|
||||
AC_MSG_RESULT(yes)
|
||||
if test "x$OPENSSL_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="OPENSSL_"
|
||||
elif test "x$GNUTLS_ENABLED" == "x1"; then
|
||||
elif test "x$GNUTLS_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="GNUTLS_"
|
||||
elif test "x$NSS_ENABLED" == "x1"; then
|
||||
elif test "x$NSS_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="NSS_"
|
||||
elif test "x$POLARSSL_ENABLED" == "x1"; then
|
||||
elif test "x$POLARSSL_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="POLARSSL_"
|
||||
elif test "x$CYASSL_ENABLED" == "x1"; then
|
||||
elif test "x$CYASSL_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="CYASSL_"
|
||||
elif test "x$AXTLS_ENABLED" == "x1"; then
|
||||
elif test "x$AXTLS_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="AXTLS_"
|
||||
elif test "x$WINSSL_ENABLED" == "x1"; then
|
||||
elif test "x$WINSSL_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="WINSSL_"
|
||||
elif test "x$DARWINSSL_ENABLED" == "x1"; then
|
||||
elif test "x$DARWINSSL_ENABLED" = "x1"; then
|
||||
versioned_symbols_flavour="DARWINSSL_"
|
||||
else
|
||||
versioned_symbols_flavour=""
|
||||
@@ -3246,6 +3249,7 @@ AC_HELP_STRING([--disable-crypto-auth],[Disable cryptographic authentication]),
|
||||
no)
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE(CURL_DISABLE_CRYPTO_AUTH, 1, [to disable cryptographic authentication])
|
||||
CURL_DISABLE_CRYPTO_AUTH=1
|
||||
;;
|
||||
*) AC_MSG_RESULT(yes)
|
||||
;;
|
||||
@@ -3379,7 +3383,8 @@ fi
|
||||
if test "x$USE_WINDOWS_SSPI" = "x1"; then
|
||||
SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI"
|
||||
fi
|
||||
if test "x$CURL_DISABLE_HTTP" != "x1"; then
|
||||
if test "x$CURL_DISABLE_HTTP" != "x1" -a \
|
||||
"x$CURL_DISABLE_CRYPTO_AUTH" != "x1"; then
|
||||
if test "x$USE_SSLEAY" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
|
||||
-o "x$GNUTLS_ENABLED" = "x1" -o "x$NSS_ENABLED" = "x1" \
|
||||
-o "x$DARWINSSL_ENABLED" = "x1"; then
|
||||
@@ -3542,7 +3547,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
|
||||
SSL support: ${curl_ssl_msg}
|
||||
SSH support: ${curl_ssh_msg}
|
||||
zlib support: ${curl_zlib_msg}
|
||||
GSSAPI support: ${curl_gss_msg}
|
||||
GSS-API support: ${curl_gss_msg}
|
||||
SPNEGO support: ${curl_spnego_msg}
|
||||
TLS-SRP support: ${curl_tls_srp_msg}
|
||||
resolver: ${curl_res_msg}
|
||||
|
||||
@@ -59,7 +59,7 @@ GnuTLS
|
||||
OpenSSL does. Now, you can build and distribute an TLS/SSL capable libcurl
|
||||
without including any Original BSD licensed code.
|
||||
|
||||
I believe Debian is the first (only?) distro that provides libcurl/GnutTLS
|
||||
I believe Debian is the first (only?) distro that provides libcurl/GnuTLS
|
||||
packages.
|
||||
|
||||
yassl
|
||||
@@ -72,20 +72,20 @@ GnuTLS vs OpenSSL vs yassl
|
||||
|
||||
While these three libraries offer similar features, they are not equal.
|
||||
libcurl does not (yet) offer a standardized stable ABI if you decide to
|
||||
switch from using libcurl-openssl to libcurl-gnutls or vice versa. The GnuTLS
|
||||
switch from using libcurl-openssl to libcurl-gnutls or vice-versa. The GnuTLS
|
||||
and yassl support is very recent in libcurl and it has not been tested nor
|
||||
used very extensively, while the OpenSSL equivalent code has been used and
|
||||
thus matured since 1999.
|
||||
|
||||
GnuTLS
|
||||
- LGPL licensened
|
||||
- LGPL licensed
|
||||
- supports SRP
|
||||
- lacks SSLv2 support
|
||||
- lacks MD2 support (used by at least some CA certs)
|
||||
- lacks the crypto functions libcurl uses for NTLM
|
||||
|
||||
OpenSSL
|
||||
- Original BSD licensened
|
||||
- Original BSD licensed
|
||||
- lacks SRP
|
||||
- supports SSLv2
|
||||
- older and more widely used
|
||||
|
||||
@@ -55,7 +55,7 @@ HTTP
|
||||
- reads/writes the netscape cookie file format
|
||||
- custom headers (replace/remove internally generated headers)
|
||||
- custom user-agent string
|
||||
- custom referer string
|
||||
- custom referrer string
|
||||
- range
|
||||
- proxy authentication
|
||||
- time conditions
|
||||
@@ -161,8 +161,8 @@ IMAP
|
||||
- SASL based authentication: Plain, Login, CRAM-MD5, Digest-MD5 and
|
||||
NTLM (*9)
|
||||
- list the folders of a mailbox
|
||||
- select a mailbox with support for verifing the UIDVALIDITY
|
||||
- fetch e-mails with support for specifing the UID and SECTION
|
||||
- select a mailbox with support for verifying the UIDVALIDITY
|
||||
- fetch e-mails with support for specifying the UID and SECTION
|
||||
- upload e-mails via the append command
|
||||
- enhanced command support for: EXAMINE, CREATE, DELETE, RENAME, STATUS,
|
||||
STORE, COPY and UID via custom requests
|
||||
|
||||
15
docs/INSTALL
15
docs/INSTALL
@@ -115,18 +115,6 @@ UNIX
|
||||
|
||||
./configure --disable-thread
|
||||
|
||||
To build curl with kerberos4 support enabled, curl requires the krb4 libs
|
||||
and headers installed. You can then use a set of options to tell
|
||||
configure where those are:
|
||||
|
||||
--with-krb4-includes[=DIR] Specify location of kerberos4 headers
|
||||
--with-krb4-libs[=DIR] Specify location of kerberos4 libs
|
||||
--with-krb4[=DIR] where to look for Kerberos4
|
||||
|
||||
In most cases, /usr/athena is the install prefix and then it works with
|
||||
|
||||
./configure --with-krb4=/usr/athena
|
||||
|
||||
If you're a curl developer and use gcc, you might want to enable more
|
||||
debug options with the --enable-debug option.
|
||||
|
||||
@@ -1013,7 +1001,7 @@ REDUCING SIZE
|
||||
|
||||
Using these techniques it is possible to create a basic HTTP-only shared
|
||||
libcurl library for i386 Linux platforms that is only 114 KiB in size, and
|
||||
an FTP-only library that is 115 KiB in size (as of libcurl version 7.34.1,
|
||||
an FTP-only library that is 115 KiB in size (as of libcurl version 7.35.0,
|
||||
using gcc 4.8.2).
|
||||
|
||||
You may find that statically linking libcurl to your application will
|
||||
@@ -1026,7 +1014,6 @@ REDUCING SIZE
|
||||
command line. Following is a list of appropriate key words:
|
||||
|
||||
--disable-cookies !cookies
|
||||
--disable-crypto-auth !HTTP\ Digest\ auth !HTTP\ proxy\ Digest\ auth
|
||||
--disable-manual !--manual
|
||||
--disable-proxy !HTTP\ proxy !proxytunnel !SOCKS4 !SOCKS5
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ Command Line CMake
|
||||
|
||||
$ make install
|
||||
|
||||
(The teste suit does not work with the cmake build)
|
||||
(The test suite does not work with the cmake build)
|
||||
|
||||
ccmake
|
||||
=========
|
||||
|
||||
@@ -45,6 +45,7 @@ Portability
|
||||
qsossl V5R3M0
|
||||
NSS 3.14.x
|
||||
axTLS 1.2.7
|
||||
PolarSSL 1.3.0
|
||||
Heimdal ?
|
||||
|
||||
On systems where configure runs, we aim at working on them all - if they have
|
||||
@@ -300,7 +301,7 @@ Persistent Connections
|
||||
o When libcurl is told to perform a transfer, it first checks for an already
|
||||
existing connection in the cache that we can use. Otherwise it creates a
|
||||
new one and adds that the cache. If the cache is full already when a new
|
||||
conncetion is added added, it will first close the oldest unused one.
|
||||
connection is added added, it will first close the oldest unused one.
|
||||
o When the transfer operation is complete, the connection is left
|
||||
open. Particular options may tell libcurl not to, and protocols may signal
|
||||
closure on connections and then they won't be kept open of course.
|
||||
|
||||
@@ -6,13 +6,13 @@ 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
|
||||
mention that decoding also means that we need to check for nastiness 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
|
||||
and SMTP if a failure occurs during the authentication phase of a
|
||||
connection.
|
||||
|
||||
85. Wrong STARTTRANSFER timer accounting for POST requests
|
||||
@@ -38,9 +38,9 @@ may have been fixed since this was written!
|
||||
such in the build.
|
||||
http://curl.haxx.se/bug/view.cgi?id=1222
|
||||
|
||||
81. When using -J (with -O), automaticly resumed downloading together with "-C
|
||||
-" fails. Without -J the same command line works! This happens because the
|
||||
resume logic is worked out before the target file name (and thus its
|
||||
81. When using -J (with -O), automatically resumed downloading together with
|
||||
"-C -" fails. Without -J the same command line works! This happens because
|
||||
the resume logic is worked out before the target file name (and thus its
|
||||
pre-transfer size) has been figured out!
|
||||
http://curl.haxx.se/bug/view.cgi?id=1169
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ for older and later versions as things don't change drastically that often.
|
||||
->mstate is the multi state of this particular SessionHandle. When
|
||||
multi_runsingle() is called, it will act on this handle according to which
|
||||
state it is in. The mstate is also what tells which sockets to return for a
|
||||
speicific SessionHandle when curl_multi_fdset() is called etc.
|
||||
specific SessionHandle when curl_multi_fdset() is called etc.
|
||||
|
||||
The libcurl source code generally use the name 'data' for the variable that
|
||||
points to the SessionHandle.
|
||||
@@ -60,7 +60,7 @@ for older and later versions as things don't change drastically that often.
|
||||
re-use an existing one instead of creating a new as it creates a significant
|
||||
performance boost.
|
||||
|
||||
Each 'connectdata' identifies a single physical conncetion to a server. If
|
||||
Each 'connectdata' identifies a single physical connection to a server. If
|
||||
the connection can't be kept alive, the connection will be closed after use
|
||||
and then this struct can be removed from the cache and freed.
|
||||
|
||||
@@ -158,18 +158,18 @@ for older and later versions as things don't change drastically that often.
|
||||
|
||||
->do_it is the function called to issue the transfer request. What we call
|
||||
the DO action internally. If the DO is not enough and things need to be kept
|
||||
getting done for the entier DO sequence to complete, ->doing is then usually
|
||||
getting done for the entire DO sequence to complete, ->doing is then usually
|
||||
also provided. Each protocol that needs to do multiple commands or similar
|
||||
for do/doing need to implement their own state machines (see SCP, SFTP,
|
||||
FTP). Some protocols (only FTP and only due to historical reasons) has a
|
||||
separate piece of the DO state called DO_MORE.
|
||||
|
||||
->doing keeps getting called while issudeing the transfer request command(s)
|
||||
->doing keeps getting called while issuing the transfer request command(s)
|
||||
|
||||
->done gets called when the transfer is complete and DONE. That's after the
|
||||
main data has been transferred.
|
||||
|
||||
->do_more gets called doring the DO_MORE state. The FTP protocol uses this
|
||||
->do_more gets called during the DO_MORE state. The FTP protocol uses this
|
||||
state when setting up the second connection.
|
||||
|
||||
->proto_getsock
|
||||
|
||||
@@ -105,7 +105,7 @@ MAIL ETIQUETTE
|
||||
No matter what, we NEVER EVER respond to trolls or spammers on the list. If
|
||||
you believe the list admin should do something particular, contact him/her
|
||||
off-list. The subject will be taken care of as good as possible to prevent
|
||||
repeated offences, but responding on the list to such messages never lead to
|
||||
repeated offenses, but responding on the list to such messages never lead to
|
||||
anything good and only puts the light even more on the offender: which was
|
||||
the entire purpose of it getting to the list in the first place.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2014, 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
|
||||
@@ -37,7 +37,8 @@ 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 SECURITY RELEASE-PROCEDURE
|
||||
MAIL-ETIQUETTE HTTP-COOKIES LIBCURL-STRUCTS SECURITY RELEASE-PROCEDURE \
|
||||
SSL-PROBLEMS
|
||||
|
||||
MAN2HTML= roffit < $< >$@
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ README.netware
|
||||
|
||||
Curl has been successfully compiled with gcc / nlmconv on different flavours
|
||||
of Linux as well as with the official Metrowerks CodeWarrior compiler.
|
||||
While not being the main development target, a continously growing share of
|
||||
While not being the main development target, a continuously growing share of
|
||||
curl users are NetWare-based, specially also consuming the lib from PHP.
|
||||
|
||||
The unix-style man pages are tricky to read on windows, so therefore are all
|
||||
|
||||
@@ -60,7 +60,7 @@ announcement.
|
||||
|
||||
- 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
|
||||
workarounds, 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
|
||||
@@ -85,7 +85,7 @@ announcement.
|
||||
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
|
||||
- The security web page on the web site should get the new vulnerability
|
||||
mentioned.
|
||||
|
||||
[1] = http://oss-security.openwall.org/wiki/mailing-lists/distros
|
||||
|
||||
67
docs/SSL-PROBLEMS
Normal file
67
docs/SSL-PROBLEMS
Normal file
@@ -0,0 +1,67 @@
|
||||
_ _ ____ _
|
||||
___| | | | _ \| |
|
||||
/ __| | | | |_) | |
|
||||
| (__| |_| | _ <| |___
|
||||
\___|\___/|_| \_\_____|
|
||||
|
||||
SSL problems
|
||||
|
||||
First, let's establish that we often refer to TLS and SSL interchangeably as
|
||||
SSL here. The current protocol is called TLS, it was called SSL a long time
|
||||
ago.
|
||||
|
||||
There are several known reasons why a connection that involves SSL might
|
||||
fail. This is a document that attempts to details the most common ones and
|
||||
how to mitigate them.
|
||||
|
||||
CA certs
|
||||
|
||||
CA certs are used to digitally verify the server's certificate. You need a
|
||||
"ca bundle" for this. See lots of more details on this in the SSLCERTS
|
||||
document.
|
||||
|
||||
CA bundle missing intermediate certificates
|
||||
|
||||
When using said CA bundle to verify a server cert, you will experience
|
||||
problems if your CA cert does not have the certificates for the
|
||||
intermediates in the whole trust chain.
|
||||
|
||||
SSL version
|
||||
|
||||
Some broken servers fail to support the protocol negotiation properly that
|
||||
SSL servers are supposed to handle. This may cause the connection to fail
|
||||
completely. Sometimes you may need to explicitly select a SSL version to use
|
||||
when connecting to make the connection succeed.
|
||||
|
||||
An additional complication can be that modern SSL libraries sometimes are
|
||||
built with support for older SSL and TLS versions disabled!
|
||||
|
||||
SSL ciphers
|
||||
|
||||
Clients give servers a list of ciphers to select from. If the list doesn't
|
||||
include any ciphers the server wants/can use, the connection handshake
|
||||
fails.
|
||||
|
||||
curl has recently disabled the user of a whole bunch of seriously insecure
|
||||
ciphers from its default set (slightly depending on SSL backend in use).
|
||||
|
||||
You may have to explicitly provide an alternative list of ciphers for curl
|
||||
to use to allow the server to use a WEAK cipher for you.
|
||||
|
||||
Note that these weak ciphers are identified as flawed. For example, this
|
||||
includes symmetric ciphers with less than 128 bit keys and RC4.
|
||||
|
||||
References:
|
||||
|
||||
http://tools.ietf.org/html/draft-popov-tls-prohibiting-rc4-01
|
||||
|
||||
Allow BEAST
|
||||
|
||||
BEAST is the name of a TLS 1.0 attack that surfaced 2011. When adding means
|
||||
to mitigate this attack, it turned out that some broken servers out there in
|
||||
the wild didn't work properly with the BEAST mitigation in place.
|
||||
|
||||
To make such broken servers work, the --ssl-allow-beast option was
|
||||
introduced. Exactly as it sounds, it re-introduces the BEAST vulnerability
|
||||
but on the other hand it allows curl to connect to that kind of strange
|
||||
servers.
|
||||
@@ -110,7 +110,7 @@ Starting with version 7.19.7, libcurl will check for the NSS version it runs,
|
||||
and automatically add the 'sql:' prefix to the certdb directory (either the
|
||||
hardcoded default /etc/pki/nssdb or the directory configured with SSL_DIR
|
||||
environment variable) if version 3.12.0 or later is detected. To check which
|
||||
ertdb format your distribution provides, examine the default
|
||||
certdb format your distribution provides, examine the default
|
||||
certdb location: /etc/pki/nssdb; the new certdb format can be identified by
|
||||
the filenames cert9.db, key4.db, pkcs11.txt; filenames of older versions are
|
||||
cert8.db, key3.db, modsec.db.
|
||||
|
||||
33
docs/THANKS
33
docs/THANKS
@@ -6,9 +6,11 @@
|
||||
|
||||
Aaron Oneal
|
||||
Aaron Orenstein
|
||||
Abram Pousada
|
||||
Adam D. Moss
|
||||
Adam Light
|
||||
Adam Piggott
|
||||
Adam Sampson
|
||||
Adam Tkac
|
||||
Adrian Schuur
|
||||
Adriano Meirelles
|
||||
@@ -93,12 +95,14 @@ Arnaud Compan
|
||||
Arnaud Ebalard
|
||||
Arthur Murray
|
||||
Arve Knudsen
|
||||
Arvid Norberg
|
||||
Ates Goral
|
||||
Augustus Saunders
|
||||
Avery Fay
|
||||
Axel Tillequin
|
||||
Balaji Parasuram
|
||||
Balint Szilakszi
|
||||
Barry Abrahamson
|
||||
Bart Whiteley
|
||||
Bas Mevissen
|
||||
Ben Darnell
|
||||
@@ -131,6 +135,7 @@ Bogdan Nicula
|
||||
Brad Burdick
|
||||
Brad Hards
|
||||
Brad King
|
||||
Brad Spencer
|
||||
Bradford Bruce
|
||||
Brandon Wang
|
||||
Brendan Jurd
|
||||
@@ -155,6 +160,7 @@ Cedric Deltheil
|
||||
Chad Monroe
|
||||
Chandrakant Bagul
|
||||
Charles Kerr
|
||||
Chen Prog
|
||||
Chih-Chung Chang
|
||||
Chris "Bob Bob"
|
||||
Chris Combes
|
||||
@@ -248,6 +254,7 @@ David McCreedy
|
||||
David Odin
|
||||
David Phillips
|
||||
David Rosenstrauch
|
||||
David Ryskalczyk
|
||||
David Shaw
|
||||
David Strauss
|
||||
David Tarendash
|
||||
@@ -327,6 +334,7 @@ Eugene Kotlyarov
|
||||
Evan Jordan
|
||||
Evgeny Turnaev
|
||||
Eygene Ryabinkin
|
||||
Fabian Frank
|
||||
Fabian Hiernaux
|
||||
Fabian Keil
|
||||
Fabrizio Ammollo
|
||||
@@ -357,6 +365,7 @@ Gautam Kachroo
|
||||
Gautam Mani
|
||||
Gavrie Philipson
|
||||
Gaz Iqbal
|
||||
Gaël Portay
|
||||
Geoff Beier
|
||||
Georg Horn
|
||||
Georg Huettenegger
|
||||
@@ -378,6 +387,7 @@ Giuseppe Attardi
|
||||
Giuseppe D'Ambrosio
|
||||
Glen Nakamura
|
||||
Glen Scott
|
||||
Glenn Sheridan
|
||||
Gokhan Sengun
|
||||
Gordon Marler
|
||||
Gorilla Maguila
|
||||
@@ -416,6 +426,7 @@ Ho-chi Chen
|
||||
Hoi-Ho Chan
|
||||
Hongli Lai
|
||||
Howard Chu
|
||||
Hubert Kario
|
||||
Hzhijun
|
||||
Ian D Allen
|
||||
Ian Ford
|
||||
@@ -427,6 +438,7 @@ Ignacio Vazquez-Abrams
|
||||
Igor Franchuk
|
||||
Igor Novoseltsev
|
||||
Igor Polyakov
|
||||
Iida Yosiaki
|
||||
Ilguiz Latypov
|
||||
Ilja van Sprundel
|
||||
Immanuel Gregoire
|
||||
@@ -475,6 +487,7 @@ Jean-Marc Ranger
|
||||
Jean-Noel Rouvignac
|
||||
Jean-Philippe Barrette-LaPierre
|
||||
Jeff Connelly
|
||||
Jeff Hodges
|
||||
Jeff Johnson
|
||||
Jeff King
|
||||
Jeff Lawson
|
||||
@@ -498,6 +511,7 @@ Jim Hollinger
|
||||
Jim Meyering
|
||||
Jiri Hruska
|
||||
Jiri Jaburek
|
||||
Jiri Malak
|
||||
Jocelyn Jaubert
|
||||
Joe Halpin
|
||||
Joe Malicki
|
||||
@@ -556,6 +570,7 @@ Jun-ichiro itojun Hagino
|
||||
Jurij Smakov
|
||||
Justin Fletcher
|
||||
Justin Karneges
|
||||
Justin Maggard
|
||||
Jörg Mueller-Tolk
|
||||
Jörn Hartroth
|
||||
Kai Engert
|
||||
@@ -610,6 +625,7 @@ Lau Hang Kin
|
||||
Laurent Rabret
|
||||
Legoff Vincent
|
||||
Lehel Bernadt
|
||||
Leif W
|
||||
Len Krause
|
||||
Lenaic Lefever
|
||||
Lenny Rachitsky
|
||||
@@ -630,9 +646,11 @@ Ludovico Cavedon
|
||||
Lukasz Czekierda
|
||||
Luke Amery
|
||||
Luke Call
|
||||
Luke Dashjr
|
||||
Luong Dinh Dung
|
||||
Maciej Karpiuk
|
||||
Maciej W. Rozycki
|
||||
Maks Naumov
|
||||
Mamoru Tasaka
|
||||
Mandy Wu
|
||||
Manfred Schwarb
|
||||
@@ -730,6 +748,7 @@ Mike Bytnar
|
||||
Mike Crowe
|
||||
Mike Dobbs
|
||||
Mike Giancola
|
||||
Mike Hasselberg
|
||||
Mike Hommey
|
||||
Mike Mio
|
||||
Mike Power
|
||||
@@ -738,6 +757,7 @@ Mike Revi
|
||||
Miklos Nemeth
|
||||
Mitz Wark
|
||||
Mohamed Lrhazi
|
||||
Mohammad AlSaleh
|
||||
Mohun Biswas
|
||||
Moonesamy
|
||||
Myk Taylor
|
||||
@@ -784,6 +804,7 @@ Oscar Koeroo
|
||||
Oscar Norlander
|
||||
P R Schaffner
|
||||
Paolo Piacentini
|
||||
Paras Sethia
|
||||
Pascal Terjan
|
||||
Pasha Kuznetsov
|
||||
Pat Ray
|
||||
@@ -828,6 +849,7 @@ Peter Verhas
|
||||
Peter Wullinger
|
||||
Peteris Krumins
|
||||
Petr Bahula
|
||||
Petr Novak
|
||||
Petr Pisar
|
||||
Phil Blundell
|
||||
Phil Karn
|
||||
@@ -846,6 +868,8 @@ Pierre Joye
|
||||
Pierre Ynard
|
||||
Pooyan McSporran
|
||||
Pramod Sharma
|
||||
Prash Dush
|
||||
Priyanka Shah
|
||||
Puneet Pawaia
|
||||
Quagmire
|
||||
Quanah Gibson-Mount
|
||||
@@ -865,6 +889,7 @@ Ravi Pratap
|
||||
Ray Dassen
|
||||
Ray Pekowski
|
||||
Reinout van Schouwen
|
||||
Remi Gacogne
|
||||
Renato Botelho
|
||||
Renaud Chaillat
|
||||
Renaud Duhaut
|
||||
@@ -888,6 +913,7 @@ Richard Silverman
|
||||
Rick Jones
|
||||
Rick Richardson
|
||||
Rob Crittenden
|
||||
Rob Davies
|
||||
Rob Jones
|
||||
Rob Stanzel
|
||||
Rob Ward
|
||||
@@ -952,6 +978,7 @@ Sergey Tatarincev
|
||||
Sergio Ballestrero
|
||||
Seshubabu Pasam
|
||||
Sh Diao
|
||||
Shao Shuchao
|
||||
Sharad Gupta
|
||||
Shard
|
||||
Shawn Landden
|
||||
@@ -1005,12 +1032,14 @@ Taneli Vahakangas
|
||||
Tanguy Fautre
|
||||
Tatsuhiro Tsujikawa
|
||||
Temprimus
|
||||
Thomas Braun
|
||||
Thomas J. Moore
|
||||
Thomas Klausner
|
||||
Thomas L. Shinnick
|
||||
Thomas Lopatic
|
||||
Thomas Schwinge
|
||||
Thomas Tonino
|
||||
Tiit Pikma
|
||||
Tim Ansell
|
||||
Tim Baker
|
||||
Tim Bartley
|
||||
@@ -1022,6 +1051,7 @@ Tim Newsome
|
||||
Tim Sneddon
|
||||
Timo Sirainen
|
||||
Tinus van den Berg
|
||||
Tobias Markus
|
||||
Tobias Rundström
|
||||
Toby Peterson
|
||||
Todd A Ouska
|
||||
@@ -1064,6 +1094,7 @@ Ulrich Zadow
|
||||
Venkat Akella
|
||||
Victor Snezhko
|
||||
Vikram Saxena
|
||||
Viktor Szakáts
|
||||
Vilmos Nebehaj
|
||||
Vincent Bronner
|
||||
Vincent Le Normand
|
||||
@@ -1095,8 +1126,10 @@ Yaakov Selkowitz
|
||||
Yamada Yasuharu
|
||||
Yang Tse
|
||||
Yarram Sunil
|
||||
Yehezkel Horowitz
|
||||
Yehoshua Hershberg
|
||||
Yi Huang
|
||||
Yingwei Liu
|
||||
Yukihiro Kawada
|
||||
Yuriy Sosov
|
||||
Yves Arrouye
|
||||
|
||||
47
docs/TODO
47
docs/TODO
@@ -38,7 +38,7 @@
|
||||
5.1 Better persistency for HTTP 1.0
|
||||
5.2 support FF3 sqlite cookie files
|
||||
5.3 Rearrange request header order
|
||||
5.4 HTTP2/SPDY
|
||||
5.4 SPDY
|
||||
5.5 auth= in URLs
|
||||
|
||||
6. TELNET
|
||||
@@ -87,9 +87,8 @@
|
||||
15.3 prevent file overwriting
|
||||
15.4 simultaneous parallel transfers
|
||||
15.5 provide formpost headers
|
||||
15.6 url-specific options
|
||||
15.7 warning when setting an option
|
||||
15.8 IPv6 addresses with globbing
|
||||
15.6 warning when setting an option
|
||||
15.7 IPv6 addresses with globbing
|
||||
|
||||
16. Build
|
||||
16.1 roffit
|
||||
@@ -273,23 +272,13 @@
|
||||
headers use a default value so only headers that need to be moved have to be
|
||||
specified.
|
||||
|
||||
5.4 HTTP2/SPDY
|
||||
5.4 SPDY
|
||||
|
||||
The first drafts for HTTP2 have been published
|
||||
(http://tools.ietf.org/html/draft-ietf-httpbis-http2-03) and is so far based
|
||||
on SPDY (http://www.chromium.org/spdy) designs and experiences. Chances are
|
||||
it will end up in that style. Chrome and Firefox already support SPDY and
|
||||
lots of web services do.
|
||||
Chrome and Firefox already support SPDY and lots of web services do. There's
|
||||
a library for us to use for this (spdylay) that has a similar API and the
|
||||
same author as nghttp2.
|
||||
|
||||
It would make sense to implement SPDY support now and later transition into
|
||||
or add HTTP2 support as well.
|
||||
|
||||
We should base or HTTP2/SPDY work on a 3rd party library for the protocol
|
||||
fiddling. The Spindy library (http://spindly.haxx.se/) was an attempt to make
|
||||
such a library with an API suitable for use by libcurl but that effort has
|
||||
more or less stalled. spdylay (https://github.com/tatsuhiro-t/spdylay) may
|
||||
be a better option, either used directly or wrapped with a more spindly-like
|
||||
API.
|
||||
spdylay: https://github.com/tatsuhiro-t/spdylay
|
||||
|
||||
5.5 auth= in URLs
|
||||
|
||||
@@ -494,27 +483,13 @@ to provide the data to send.
|
||||
which should overwrite the program reasonable defaults (plain/text,
|
||||
8bit...)
|
||||
|
||||
15.6 url-specific options
|
||||
|
||||
Provide a way to make options bound to a specific URL among several on the
|
||||
command line. Possibly by letting ':' separate options between URLs,
|
||||
similar to this:
|
||||
|
||||
curl --data foo --url url.com : \
|
||||
--url url2.com : \
|
||||
--url url3.com --data foo3
|
||||
|
||||
(More details: http://curl.haxx.se/mail/archive-2004-07/0133.html)
|
||||
|
||||
The example would do a POST-GET-POST combination on a single command line.
|
||||
|
||||
15.7 warning when setting an option
|
||||
15.6 warning when setting an option
|
||||
|
||||
Display a warning when libcurl returns an error when setting an option.
|
||||
This can be useful to tell when support for a particular feature hasn't been
|
||||
compiled into the library.
|
||||
|
||||
15.8 IPv6 addresses with globbing
|
||||
15.7 IPv6 addresses with globbing
|
||||
|
||||
Currently the command line client needs to get url globbing disabled (with
|
||||
-g) for it to support IPv6 numerical addresses. This is a rather silly flaw
|
||||
@@ -590,7 +565,7 @@ to provide the data to send.
|
||||
for applications to differentiate on TCP vs UDP and even HTTP vs FTP and
|
||||
similar.
|
||||
|
||||
10. Next major release
|
||||
19. Next major release
|
||||
|
||||
19.1 cleanup return codes
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ The Art Of Scripting HTTP Requests Using Curl
|
||||
2.4 User name and password
|
||||
|
||||
Some services are setup to require HTTP authentication and then you need to
|
||||
provide name and password which then is transfered to the remote site in
|
||||
provide name and password which then is transferred to the remote site in
|
||||
various ways depending on the exact authentication protocol used.
|
||||
|
||||
You can opt to either insert the user and password in the URL or you can
|
||||
@@ -520,7 +520,7 @@ The Art Of Scripting HTTP Requests Using Curl
|
||||
|
||||
Curl has a full blown cookie parsing engine built-in that comes to use if you
|
||||
want to reconnect to a server and use cookies that were stored from a
|
||||
previous connection (or handicrafted manually to fool the server into
|
||||
previous connection (or hand-crafted manually to fool the server into
|
||||
believing you had a previous connection). To use previously stored cookies,
|
||||
you run curl like:
|
||||
|
||||
@@ -645,7 +645,7 @@ The Art Of Scripting HTTP Requests Using Curl
|
||||
sometimes they use such code to set or modify cookie contents. Possibly they
|
||||
do that to prevent programmed logins, like this manual describes how to...
|
||||
Anyway, if reading the code isn't enough to let you repeat the behavior
|
||||
manually, capturing the HTTP requests done by your browers and analyzing the
|
||||
manually, capturing the HTTP requests done by your browsers and analyzing the
|
||||
sent cookies is usually a working method to work out how to shortcut the
|
||||
javascript need.
|
||||
|
||||
|
||||
36
docs/curl.1
36
docs/curl.1
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, 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
|
||||
@@ -124,18 +124,38 @@ same command line option.)
|
||||
.IP "-#, --progress-bar"
|
||||
Make curl display progress as a simple progress bar instead of the standard,
|
||||
more informational, meter.
|
||||
.IP "-:, --next"
|
||||
Tells curl to use a separate operation for the following URL and associated
|
||||
options. This allows you to send several URL requests, each with their own
|
||||
specific options, for example, such as different user names or custom requests
|
||||
for each. (Added in 7.36.0)
|
||||
.IP "-0, --http1.0"
|
||||
(HTTP) Tells curl to use HTTP version 1.0 instead of using its internally
|
||||
preferred: HTTP 1.1.
|
||||
.IP "--http1.1"
|
||||
(HTTP) Tells curl to use HTTP version 1.1. This is the internal default
|
||||
version. (Added in 7.33.0)
|
||||
.IP "--http2.0"
|
||||
(HTTP) Tells curl to issue its requests using HTTP 2.0. This requires that the
|
||||
.IP "--http2"
|
||||
(HTTP) Tells curl to issue its requests using HTTP 2. This requires that the
|
||||
underlying libcurl was built to support it. (Added in 7.33.0)
|
||||
.IP "--no-npn"
|
||||
Disable the NPN TLS extension. NPN is enabled by default if libcurl was built
|
||||
with an SSL library that supports NPN. NPN is used by a libcurl that supports
|
||||
HTTP 2 to negotiate HTTP 2 support with the server during https sessions.
|
||||
|
||||
(Added in 7.36.0)
|
||||
.IP "--no-alpn"
|
||||
Disable the ALPN TLS extension. ALPN is enabled by default if libcurl was built
|
||||
with an SSL library that supports ALPN. ALPN is used by a libcurl that supports
|
||||
HTTP 2 to negotiate HTTP 2 support with the server during https sessions.
|
||||
|
||||
(Added in 7.36.0)
|
||||
.IP "-1, --tlsv1"
|
||||
(SSL)
|
||||
Forces curl to use TLS version 1 when negotiating with a remote TLS server.
|
||||
Forces curl to use TLS version 1.x when negotiating with a remote TLS server.
|
||||
You can use options \fI--tlsv1.0\fP, \fI--tlsv1.1\fP, and \fI--tlsv1.2\fP to
|
||||
control the TLS version more precisely (if the SSL backend in use supports such
|
||||
a level of control).
|
||||
.IP "-2, --sslv2"
|
||||
(SSL)
|
||||
Forces curl to use SSL version 2 when negotiating with a remote SSL server.
|
||||
@@ -422,7 +442,7 @@ This option requires that libcurl was built with a resolver backend that
|
||||
supports this operation. The c-ares backend is the only such one. (Added in
|
||||
7.33.0)
|
||||
.IP "-e, --referer <URL>"
|
||||
(HTTP) Sends the "Referer Page" information to the HTTP server. This can also
|
||||
(HTTP) Sends the "Referrer Page" information to the HTTP server. This can also
|
||||
be set with the \fI-H, --header\fP flag of course. When used with
|
||||
\fI-L, --location\fP you can append ";auto" to the --referer URL to make curl
|
||||
automatically set the previous URL when it follows a Location: header. The
|
||||
@@ -1404,7 +1424,7 @@ option name can still be used but will be removed in a future version.
|
||||
.IP "--ssl-allow-beast"
|
||||
(SSL) This option tells curl to not work around a security flaw in the SSL3
|
||||
and TLS1.0 protocols known as BEAST. If this option isn't used, the SSL layer
|
||||
may use work-arounds known to cause interoperability problems with some older
|
||||
may use workarounds known to cause interoperability problems with some older
|
||||
SSL implementations. WARNING: this option loosens the SSL security, and by
|
||||
using this flag you ask for exactly that. (Added in 7.25.0)
|
||||
.IP "--socks4 <host[:port]>"
|
||||
@@ -1581,7 +1601,7 @@ will prompt for a password.
|
||||
|
||||
If you use an SSPI-enabled curl binary and perform NTLM authentication, you
|
||||
can force curl to select the user name and password from your environment by
|
||||
simply specifying a single colon with this option: "-u :" or by specfying the
|
||||
simply specifying a single colon with this option: "-u :" or by specifying the
|
||||
login options on their own, for example "-u ;auth=NTLM".
|
||||
|
||||
You can use the optional login options part to specify protocol specific
|
||||
@@ -1803,7 +1823,7 @@ 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)
|
||||
Specifies a custom IMAP command to use instead 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)
|
||||
|
||||
28
docs/examples/.gitignore
vendored
28
docs/examples/.gitignore
vendored
@@ -20,15 +20,39 @@ httpcustomheader
|
||||
httpput
|
||||
https
|
||||
imap
|
||||
imap-append
|
||||
imap-copy
|
||||
imap-create
|
||||
imap-delete
|
||||
imap-examine
|
||||
imap-fetch
|
||||
imap-list
|
||||
imap-multi
|
||||
imap-noop
|
||||
imap-search
|
||||
imap-ssl
|
||||
imap-store
|
||||
imap-tls
|
||||
multi-app
|
||||
multi-debugcallback
|
||||
multi-double
|
||||
multi-post
|
||||
multi-single
|
||||
persistant
|
||||
pop3-dele
|
||||
pop3-list
|
||||
pop3-multi
|
||||
pop3-noop
|
||||
pop3-retr
|
||||
pop3-ssl
|
||||
pop3-stat
|
||||
pop3-tls
|
||||
pop3-top
|
||||
pop3-uidl
|
||||
pop3s
|
||||
pop3slist
|
||||
post-callback
|
||||
postinmemory
|
||||
postit2
|
||||
progressfunc
|
||||
resolve
|
||||
@@ -40,8 +64,12 @@ simple
|
||||
simplepost
|
||||
simplesmtp
|
||||
simplessl
|
||||
smtp-expn
|
||||
smtp-mail
|
||||
smtp-multi
|
||||
smtp-ssl
|
||||
smtp-tls
|
||||
smtp-vrfy
|
||||
url2file
|
||||
usercertinmem
|
||||
xmlstream
|
||||
|
||||
@@ -7,9 +7,9 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
|
||||
smtp-mail smtp-multi smtp-ssl smtp-tls smtp-vrfy smtp-expn rtsp \
|
||||
externalsocket resolve progressfunc pop3-retr pop3-list pop3-uidl pop3-dele \
|
||||
pop3-top pop3-stat pop3-noop pop3-ssl pop3-tls pop3-multi imap-list \
|
||||
imap-fetch imap-store imap-append imap-examine imap-search imap-create \
|
||||
imap-delete imap-copy imap-noop imap-ssl imap-tls imap-multi url2file \
|
||||
sftpget ftpsget postinmemory
|
||||
imap-lsub imap-fetch imap-store imap-append imap-examine imap-search \
|
||||
imap-create imap-delete imap-copy imap-noop imap-ssl imap-tls imap-multi \
|
||||
url2file sftpget ftpsget postinmemory
|
||||
|
||||
# These examples require external dependencies that may not be commonly
|
||||
# available on POSIX systems, so don't bother attempting to compile them here.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -133,7 +133,6 @@ static void mcode_or_die(const char *where, CURLMcode code)
|
||||
const char *s;
|
||||
switch ( code )
|
||||
{
|
||||
case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
|
||||
case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break;
|
||||
case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break;
|
||||
case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -104,7 +104,6 @@ static void mcode_or_die(const char *where, CURLMcode code) {
|
||||
if ( CURLM_OK != code ) {
|
||||
const char *s;
|
||||
switch (code) {
|
||||
case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
|
||||
case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break;
|
||||
case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break;
|
||||
case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -125,7 +125,6 @@ static void mcode_or_die(const char *where, CURLMcode code)
|
||||
if ( CURLM_OK != code ) {
|
||||
const char *s;
|
||||
switch (code) {
|
||||
case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break;
|
||||
case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break;
|
||||
case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break;
|
||||
case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break;
|
||||
|
||||
62
docs/examples/imap-lsub.c
Normal file
62
docs/examples/imap-lsub.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
/* This is a simple example showing how to list the subscribed folders within
|
||||
* an IMAP mailbox.
|
||||
*
|
||||
* Note that this example requires libcurl 7.30.0 or above.
|
||||
*/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
/* Set username and password */
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, "user");
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret");
|
||||
|
||||
/* This is just the server URL */
|
||||
curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com");
|
||||
|
||||
/* Set the LSUB command. Note the syntax is very similar to that of a LIST
|
||||
command. */
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "LSUB \"\" *");
|
||||
|
||||
/* Perform the custom request */
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
/* Check for errors */
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
|
||||
/* Always cleanup */
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
return (int)res;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@@ -25,33 +25,41 @@ curl_easy_perform - Perform a file transfer
|
||||
.SH SYNOPSIS
|
||||
.B #include <curl/curl.h>
|
||||
.sp
|
||||
.BI "CURLcode curl_easy_perform(CURL *" handle ");"
|
||||
.BI "CURLcode curl_easy_perform(CURL *" easy_handle ");"
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
This function is called after the init and all the \fIcurl_easy_setopt(3)\fP
|
||||
calls are made, and will perform the transfer as described in the options. It
|
||||
must be called with the same
|
||||
.I handle
|
||||
as input as the curl_easy_init call returned.
|
||||
Invoke this function after \fIcurl_easy_init(3)\fP and all the
|
||||
\fIcurl_easy_setopt(3)\fP calls are made, and will perform the transfer as
|
||||
described in the options. It must be called with the same \fBeasy_handle\fP as
|
||||
input as the \fIcurl_easy_init(3)\fP call returned.
|
||||
|
||||
\fIcurl_easy_perform(3)\fP performs the entire request in a blocking manner
|
||||
and returns when done, or if it failed. For non-blocking behavior, see
|
||||
\fIcurl_multi_perform(3)\fP.
|
||||
|
||||
You can do any amount of calls to \fIcurl_easy_perform(3)\fP while using the
|
||||
same handle. If you intend to transfer more than one file, you are even
|
||||
encouraged to do so. libcurl will then attempt to re-use the same connection
|
||||
for the following transfers, thus making the operations faster, less CPU
|
||||
intense and using less network resources. Just note that you will have to use
|
||||
\fIcurl_easy_setopt(3)\fP between the invokes to set options for the following
|
||||
curl_easy_perform.
|
||||
same \fBeasy_handle\fP. If you intend to transfer more than one file, you are
|
||||
even encouraged to do so. libcurl will then attempt to re-use the same
|
||||
connection for the following transfers, thus making the operations faster,
|
||||
less CPU intense and using less network resources. Just note that you will
|
||||
have to use \fIcurl_easy_setopt(3)\fP between the invokes to set options for
|
||||
the following curl_easy_perform.
|
||||
|
||||
You must never call this function simultaneously from two places using the
|
||||
same handle. Let the function return first before invoking it another time. If
|
||||
you want parallel transfers, you must use several curl handles.
|
||||
same \fBeasy_handle\fP. Let the function return first before invoking it
|
||||
another time. If you want parallel transfers, you must use several curl
|
||||
easy_handles.
|
||||
|
||||
While the \fBeasy_handle\fP is added to a multi handle, it cannot be used by
|
||||
\fIcurl_easy_perform(3)\fP.
|
||||
.SH RETURN VALUE
|
||||
0 means everything was ok, non-zero means an error occurred as
|
||||
CURLE_OK (0) means everything was ok, non-zero means an error occurred as
|
||||
.I <curl/curl.h>
|
||||
defines. If the CURLOPT_ERRORBUFFER was set with
|
||||
.I curl_easy_setopt
|
||||
there will be a readable error message in the error buffer when non-zero is
|
||||
returned.
|
||||
defines - see \fIlibcurl-errors(3)\fP. If the \fBCURLOPT_ERRORBUFFER\fP was
|
||||
set with \fIcurl_easy_setopt(3)\fP there will be a readable error message in
|
||||
the error buffer when non-zero is returned.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_easy_init "(3), " curl_easy_setopt "(3), "
|
||||
.BR curl_multi_add_handle "(3), " curl_multi_perform "(3), "
|
||||
.BR libcurl-errors "(3), "
|
||||
|
||||
|
||||
@@ -493,6 +493,10 @@ The data is header (or header-like) data sent to the peer.
|
||||
The data is protocol data received from the peer.
|
||||
.IP CURLINFO_DATA_OUT
|
||||
The data is protocol data sent to the peer.
|
||||
.IP CURLINFO_SSL_DATA_OUT
|
||||
The data is SSL/TLS (binary) data sent to the peer.
|
||||
.IP CURLINFO_SSL_DATA_IN
|
||||
The data is SSL/TLS (binary) data received from the peer.
|
||||
.RE
|
||||
.IP CURLOPT_DEBUGDATA
|
||||
Pass a pointer to whatever you want passed in to your
|
||||
@@ -936,9 +940,9 @@ Set HTTP proxy to use. The parameter should be a char * to a zero terminated
|
||||
string holding the host name or dotted IP address. To specify port number in
|
||||
this string, append :[port] to the end of the host name. The proxy string may
|
||||
be prefixed with [protocol]:// since any such prefix will be ignored. The
|
||||
proxy's port number may optionally be specified with the separate option. If
|
||||
not specified, libcurl will default to using port 1080 for proxies.
|
||||
\fICURLOPT_PROXYPORT\fP.
|
||||
proxy's port number may optionally be specified with the separate option
|
||||
\fICURLOPT_PROXYPORT\fP. If not specified, libcurl will default to using port
|
||||
1080 for proxies.
|
||||
|
||||
When you tell the library to use a HTTP proxy, libcurl will transparently
|
||||
convert operations to HTTP even if you specify an FTP URL etc. This may have
|
||||
@@ -985,8 +989,8 @@ if one is specified. The only wildcard available is a single * character,
|
||||
which matches all hosts, and effectively disables the proxy. Each name in this
|
||||
list is matched as either a domain which contains the hostname, or the
|
||||
hostname itself. For example, example.com would match example.com,
|
||||
example.com:80, and www.example.com, but not www.notanexample.com. (Added in
|
||||
7.19.4)
|
||||
example.com:80, and www.example.com, but not www.notanexample.com or
|
||||
example.com.othertld. (Added in 7.19.4)
|
||||
.IP CURLOPT_HTTPPROXYTUNNEL
|
||||
Set the parameter to 1 to make the library tunnel all operations through a
|
||||
given HTTP proxy. There is a big difference between using a proxy and to
|
||||
@@ -1619,7 +1623,8 @@ When setting \fICURLOPT_HTTPGET\fP to 1, it will automatically set
|
||||
.IP CURLOPT_HTTP_VERSION
|
||||
Pass a long, set to one of the values described below. They force libcurl to
|
||||
use the specific HTTP versions. This is not sensible to do unless you have a
|
||||
good reason.
|
||||
good reason. You have to set this option if you want to use libcurl's HTTP 2.0
|
||||
support.
|
||||
.RS
|
||||
.IP CURL_HTTP_VERSION_NONE
|
||||
We don't care about what version the library uses. libcurl will use whatever
|
||||
@@ -1628,6 +1633,9 @@ it thinks fit.
|
||||
Enforce HTTP 1.0 requests.
|
||||
.IP CURL_HTTP_VERSION_1_1
|
||||
Enforce HTTP 1.1 requests.
|
||||
.IP CURL_HTTP_VERSION_2_0
|
||||
Attempt HTTP 2.0 requests. libcurl will fall back to HTTP 1.x if HTTP 2.0
|
||||
can't be negotiated with the server.
|
||||
.RE
|
||||
.IP CURLOPT_IGNORE_CONTENT_LENGTH
|
||||
Ignore the Content-Length header. This is useful for Apache 1.x (and similar
|
||||
@@ -1645,6 +1653,12 @@ Pass a long to tell libcurl how to act on transfer decoding. If set to zero,
|
||||
transfer decoding will be disabled, if set to 1 it is enabled
|
||||
(default). libcurl does chunked transfer decoding by default unless this
|
||||
option is set to zero. (added in 7.16.2)
|
||||
.IP CURLOPT_EXPECT_100_TIMEOUT_MS
|
||||
Pass a long to tell libcurl the number of milliseconds to wait for a server
|
||||
response with the HTTP status 100 (Continue), 417 (Expectation Failed) or
|
||||
similar after sending a HTTP request containing an Expect: 100-continue
|
||||
header. If this times out before a response is received, the request body is
|
||||
sent anyway. By default, libcurl waits 1000 milliseconds. (Added in 7.36.0)
|
||||
.SH SMTP OPTIONS
|
||||
.IP CURLOPT_MAIL_FROM
|
||||
Pass a pointer to a zero terminated string as parameter. This should be used
|
||||
@@ -2451,6 +2465,20 @@ load your private key.
|
||||
|
||||
(This option was known as CURLOPT_SSLKEYPASSWD up to 7.16.4 and
|
||||
CURLOPT_SSLCERTPASSWD up to 7.9.2)
|
||||
.IP CURLOPT_SSL_ENABLE_ALPN
|
||||
Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. By
|
||||
default, libcurl assumes a value of 1. This option enables/disables ALPN in
|
||||
the SSL handshake (if the SSL backend libcurl is built to use supports it),
|
||||
which can be used to negotiate http2.
|
||||
|
||||
(Added in 7.36.0)
|
||||
.IP CURLOPT_SSL_ENABLE_NPN
|
||||
Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. By
|
||||
default, libcurl assumes a value of 1. This option enables/disables NPN in the
|
||||
SSL handshake (if the SSL backend libcurl is built to use supports it), which
|
||||
can be used to negotiate http2.
|
||||
|
||||
(Added in 7.36.0)
|
||||
.IP CURLOPT_SSLENGINE
|
||||
Pass a pointer to a zero terminated string as parameter. It will be used as
|
||||
the identifier for the crypto engine you want to use for your private
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, 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
|
||||
@@ -33,8 +33,10 @@ this \fImulti_handle\fP control the specified \fIeasy_handle\fP. Furthermore,
|
||||
libcurl now initiates the connection associated with the specified
|
||||
\fIeasy_handle\fP.
|
||||
|
||||
When an easy handle has been added to a multi stack, you can not and you must
|
||||
not use \fIcurl_easy_perform(3)\fP on that handle!
|
||||
While an easy handle is added to a multi stack, you can not and you must not
|
||||
use \fIcurl_easy_perform(3)\fP on that handle. After having removed the handle
|
||||
from the multi stack again, it is perfectly fine to use it with the easy
|
||||
interface again.
|
||||
|
||||
If the easy handle is not set to use a shared (CURLOPT_SHARE) or global DNS
|
||||
cache (CURLOPT_DNS_USE_GLOBAL_CACHE), it will be made to use the DNS cache
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, 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
|
||||
@@ -28,8 +28,8 @@ curl_multi_assign \- set data to association with an internal socket
|
||||
CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd,
|
||||
void *sockptr);
|
||||
.SH DESCRIPTION
|
||||
This function assigns an association in the multi handle between the given
|
||||
socket and a private pointer of the application. This is (only) useful for
|
||||
This function creates an association in the multi handle between the given
|
||||
socket and a private pointer of the application. This is designed for
|
||||
\fIcurl_multi_socket(3)\fP uses.
|
||||
|
||||
When set, the \fIsockptr\fP pointer will be passed to all future socket
|
||||
@@ -51,13 +51,13 @@ The standard CURLMcode for multi interface error codes.
|
||||
.SH "TYPICAL USAGE"
|
||||
In a typical application you allocate a struct or at least use some kind of
|
||||
semi-dynamic data for each socket that we must wait for action on when using
|
||||
the \fIcurl_multi_socket(3)\fP approach.
|
||||
the \fIcurl_multi_socket_action(3)\fP approach.
|
||||
|
||||
When our socket-callback gets called by libcurl and we get to know about yet
|
||||
another socket to wait for, we can use \fIcurl_multi_assign(3)\fP to point out
|
||||
the particular data so that when we get updates about this same socket again,
|
||||
we don't have to find the struct associated with this socket by ourselves.
|
||||
.SH AVAILABILITY
|
||||
This function was added in libcurl 7.15.5, although not deemed stable yet.
|
||||
This function was added in libcurl 7.15.5.
|
||||
.SH "SEE ALSO"
|
||||
.BR curl_multi_setopt "(3), " curl_multi_socket "(3) "
|
||||
.BR curl_multi_setopt "(3), " curl_multi_socket_action "(3) "
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" *
|
||||
.\" * This software is licensed as described in the file COPYING, which
|
||||
.\" * you should have received as part of this distribution. The terms
|
||||
@@ -81,9 +81,9 @@ not used by libcurl but only passed-thru as-is. Set the callback pointer with
|
||||
\fICURLMOPT_TIMERFUNCTION\fP. (Added in 7.16.0)
|
||||
.IP CURLMOPT_MAXCONNECTS
|
||||
Pass a long. The set number will be used as the maximum amount of
|
||||
simultaneously open connections that libcurl may cache. Default is 10, and
|
||||
libcurl will enlarge the size for each added easy handle to make it fit 4
|
||||
times the number of added easy handles.
|
||||
simultaneously open connections that libcurl may keep in its connection cache
|
||||
after completed use. By default libcurl will enlarge the size for each added
|
||||
easy handle to make it fit 4 times the number of added easy handles.
|
||||
|
||||
By setting this option, you can prevent the cache size from growing beyond the
|
||||
limit set by you.
|
||||
@@ -94,6 +94,9 @@ number of open connections from increasing.
|
||||
This option is for the multi handle's use only, when using the easy interface
|
||||
you should instead use the \fICURLOPT_MAXCONNECTS\fP option.
|
||||
|
||||
See \fICURLMOPT_MAX_TOTAL_CONNECTIONS\fP for limiting the number of active
|
||||
connections.
|
||||
|
||||
(Added in 7.16.3)
|
||||
.IP CURLMOPT_MAX_HOST_CONNECTIONS
|
||||
Pass a long. The set number will be used as the maximum amount of
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, 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
|
||||
@@ -30,6 +30,8 @@ curl_version - returns the libcurl version string
|
||||
.SH DESCRIPTION
|
||||
Returns a human readable string with the version number of libcurl and some of
|
||||
its important components (like OpenSSL version).
|
||||
|
||||
We recommend using \fIcurl_version_info(3)\fP instead!
|
||||
.SH RETURN VALUE
|
||||
A pointer to a zero terminated string. The string resides in a statically
|
||||
allocated buffer and must not be freed by the caller.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, 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
|
||||
@@ -20,7 +20,7 @@
|
||||
.\" *
|
||||
.\" **************************************************************************
|
||||
.\"
|
||||
.TH curl_version_info 3 "10 June 2009" "libcurl 7.19.6" "libcurl Manual"
|
||||
.TH curl_version_info 3 "18 Feb 2014" "libcurl 7.33.0" "libcurl Manual"
|
||||
.SH NAME
|
||||
curl_version_info - returns run-time libcurl version info
|
||||
.SH SYNOPSIS
|
||||
@@ -30,11 +30,12 @@ curl_version_info - returns run-time libcurl version info
|
||||
.ad
|
||||
.SH DESCRIPTION
|
||||
Returns a pointer to a filled in struct with information about various
|
||||
run-time features in libcurl. \fItype\fP should be set to the version of this
|
||||
functionality by the time you write your program. This way, libcurl will
|
||||
always return a proper struct that your program understands, while programs in
|
||||
the future might get a different struct. CURLVERSION_NOW will be the most
|
||||
recent one for the library you have installed:
|
||||
features in the running version of libcurl. \fItype\fP should be set to the
|
||||
version of this functionality by the time you write your program. This way,
|
||||
libcurl will always return a proper struct that your program understands,
|
||||
while programs in the future might get a different
|
||||
struct. \fBCURLVERSION_NOW\fP will be the most recent one for the library you
|
||||
have installed:
|
||||
|
||||
data = curl_version_info(CURLVERSION_NOW);
|
||||
|
||||
@@ -133,6 +134,9 @@ libcurl was built with support for TLS-SRP. (Added in 7.21.4)
|
||||
.IP CURL_VERSION_NTLM_WB
|
||||
libcurl was built with support for NTLM delegation to a winbind helper.
|
||||
(Added in 7.22.0)
|
||||
.IP CURL_VERSION_HTTP2
|
||||
libcurl was built with support for HTTP2.
|
||||
(Added in 7.33.0)
|
||||
.RE
|
||||
\fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
|
||||
has no SSL support, this is NULL.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2014, 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
|
||||
@@ -29,22 +29,21 @@ specific man pages for each function mentioned in here. There are also the
|
||||
\fIlibcurl-share(3)\fP man page and the \fIlibcurl-tutorial(3)\fP man page for
|
||||
in-depth understanding on how to program with libcurl.
|
||||
|
||||
There are more than thirty custom bindings available that bring libcurl access
|
||||
to your favourite language. Look elsewhere for documentation on those.
|
||||
There are many bindings available that bring libcurl access to your favourite
|
||||
language. Look elsewhere for documentation on those.
|
||||
|
||||
libcurl has a global constant environment that you must set up and
|
||||
maintain while using libcurl. This essentially means you call
|
||||
libcurl has a global constant environment that you must set up and maintain
|
||||
while using libcurl. This essentially means you call
|
||||
\fIcurl_global_init(3)\fP at the start of your program and
|
||||
\fIcurl_global_cleanup(3)\fP at the end. See GLOBAL CONSTANTS below
|
||||
for details.
|
||||
\fIcurl_global_cleanup(3)\fP at the end. See \fBGLOBAL CONSTANTS\fP below for
|
||||
details.
|
||||
|
||||
To transfer files, you always set up an "easy handle" using
|
||||
\fIcurl_easy_init(3)\fP for a single specific transfer (in either
|
||||
direction). You then set your desired set of options in that handle with
|
||||
\fIcurk_easy_setopt(3)\fP. Options you set with \fIcurl_easy_setopt(3)\fP will
|
||||
be used on every repeated use of this handle until you either call the
|
||||
function again and change the option, or you reset them all with
|
||||
\fIcurl_easy_reset(3)\fP.
|
||||
To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
|
||||
for a single individual transfer (in either direction). You then set your
|
||||
desired set of options in that handle with \fIcurk_easy_setopt(3)\fP. Options
|
||||
you set with \fIcurl_easy_setopt(3)\fP stick. They will be used on every
|
||||
repeated use of this handle until you either change the option, or you reset
|
||||
them all with \fIcurl_easy_reset(3)\fP.
|
||||
|
||||
To actually transfer data you have the option of using the "easy" interface,
|
||||
or the "multi" interface.
|
||||
@@ -98,6 +97,8 @@ Unix-like operating system that ship libcurl as part of their distributions
|
||||
often don't provide the curl-config tool, but simply install the library and
|
||||
headers in the common path for this purpose.
|
||||
|
||||
Many Linux and similar sytems use pkg-config to provide build and link options
|
||||
about libraries and libcurl supports that as well.
|
||||
.SH "LIBCURL SYMBOL NAMES"
|
||||
All public functions in the libcurl interface are prefixed with 'curl_' (with
|
||||
a lowercase c). You can find other functions in the library source code, but
|
||||
@@ -115,8 +116,8 @@ several threads. libcurl is thread-safe and can be used in any number of
|
||||
threads, but you must use separate curl handles if you want to use libcurl in
|
||||
more than one thread simultaneously.
|
||||
|
||||
The global environment functions are not thread-safe. See GLOBAL CONSTANTS
|
||||
below for details.
|
||||
The global environment functions are not thread-safe. See \fBGLOBAL
|
||||
CONSTANTS\fP below for details.
|
||||
|
||||
.SH "PERSISTENT CONNECTIONS"
|
||||
Persistent connections means that libcurl can re-use the same connection for
|
||||
|
||||
@@ -341,6 +341,7 @@ CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1
|
||||
CURLOPT_EGDSOCKET 7.7
|
||||
CURLOPT_ENCODING 7.10
|
||||
CURLOPT_ERRORBUFFER 7.1
|
||||
CURLOPT_EXPECT_100_TIMEOUT_MS 7.36.0
|
||||
CURLOPT_FAILONERROR 7.1
|
||||
CURLOPT_FILE 7.1 7.9.7
|
||||
CURLOPT_FILETIME 7.5
|
||||
@@ -495,6 +496,8 @@ CURLOPT_SSLKEY 7.9.3
|
||||
CURLOPT_SSLKEYPASSWD 7.9.3 7.17.0
|
||||
CURLOPT_SSLKEYTYPE 7.9.3
|
||||
CURLOPT_SSLVERSION 7.1
|
||||
CURLOPT_SSL_ENABLE_ALPN 7.36.0
|
||||
CURLOPT_SSL_ENABLE_NPN 7.36.0
|
||||
CURLOPT_SSL_CIPHER_LIST 7.9
|
||||
CURLOPT_SSL_CTX_DATA 7.10.6
|
||||
CURLOPT_SSL_CTX_FUNCTION 7.10.6
|
||||
|
||||
@@ -1571,6 +1571,16 @@ typedef enum {
|
||||
/* Set authentication options directly */
|
||||
CINIT(LOGIN_OPTIONS, OBJECTPOINT, 224),
|
||||
|
||||
/* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
|
||||
CINIT(SSL_ENABLE_NPN, LONG, 225),
|
||||
|
||||
/* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
|
||||
CINIT(SSL_ENABLE_ALPN, LONG, 226),
|
||||
|
||||
/* Time to wait for a response to a HTTP request containing an
|
||||
* Expect: 100-continue header before sending the data anyway. */
|
||||
CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.34.1-DEV"
|
||||
#define LIBCURL_VERSION "7.36.0-DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 34
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
#define LIBCURL_VERSION_MINOR 36
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
@@ -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 0x072201
|
||||
#define LIBCURL_VERSION_NUM 0x072400
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
||||
@@ -3,16 +3,31 @@
|
||||
# G. Vanem <gvanem@broadpark.no>
|
||||
#
|
||||
|
||||
.ERASE
|
||||
|
||||
!if $(__VERSION__) < 1280
|
||||
!message !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!message ! This Open Watcom version is too old and is no longer supported !
|
||||
!message ! Please download latest version from www.openwatcom.org !
|
||||
!message !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!error Unsupported version of Open Watcom
|
||||
!endif
|
||||
|
||||
!ifndef %watcom
|
||||
!error WATCOM environment variable not set!
|
||||
!endif
|
||||
|
||||
# In order to process Makefile.inc wmake must be called with -u switch!
|
||||
!ifndef %MAKEFLAGS
|
||||
!error You MUST call wmake with the -u switch!
|
||||
!endif
|
||||
|
||||
!ifdef %libname
|
||||
LIBNAME = $(%libname)
|
||||
!else
|
||||
LIBNAME = libcurl
|
||||
!endif
|
||||
TARGETS = $(LIBNAME).dll $(LIBNAME)_imp.lib $(LIBNAME).lib
|
||||
TARGETS = $(LIBNAME).dll $(LIBNAME).lib
|
||||
|
||||
CC = wcc386
|
||||
LD = wlink
|
||||
@@ -23,37 +38,29 @@ RC = wrc
|
||||
! loaddll wcc386 wccd386
|
||||
! loaddll wpp386 wppd386
|
||||
! loaddll wlib wlibd
|
||||
! if $(__VERSION__) > 1270
|
||||
! loaddll wlink wlinkd
|
||||
! else
|
||||
! loaddll wlink wlink
|
||||
! endif
|
||||
! loaddll wlink wlinkd
|
||||
!endif
|
||||
|
||||
!ifdef __LINUX__
|
||||
DS = /
|
||||
CP = cp
|
||||
MD = mkdir -p
|
||||
RD = rmdir -p
|
||||
RM = rm -f
|
||||
!else
|
||||
DS = $(X)\$(X)
|
||||
CP = copy 2>NUL
|
||||
MD = mkdir
|
||||
RD = rmdir /q /s 2>NUL
|
||||
!if $(__VERSION__) < 1250
|
||||
RM = del /q /f 2>NUL
|
||||
!else
|
||||
RM = rm -f
|
||||
!endif
|
||||
!if $(__VERSION__) > 1290
|
||||
RD = rm -rf
|
||||
!else ifdef __UNIX__
|
||||
RD = rm -rf
|
||||
!else
|
||||
RD = rmdir /q /s 2>NUL
|
||||
!endif
|
||||
|
||||
SYS_INCL = -I$(%watcom)$(DS)h$(DS)nt -I$(%watcom)$(DS)h
|
||||
SYS_LIBS = $(%watcom)$(DS)lib386$(DS)nt;$(%watcom)$(DS)lib386
|
||||
SYS_INCL = -I"$(%watcom)/h/nt" -I"$(%watcom)/h"
|
||||
|
||||
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -zc -s -fr=con -w2 -fpi -oilrtfm &
|
||||
-wcd=201 -bt=nt -d+ -dWIN32 -dCURL_WANTS_CA_BUNDLE_ENV &
|
||||
-dBUILDING_LIBCURL -dHAVE_SPNEGO=1 -I. -I..$(DS)include $(SYS_INCL)
|
||||
-dBUILDING_LIBCURL -dHAVE_SPNEGO=1 -I. -I"../include" $(SYS_INCL)
|
||||
|
||||
!ifdef %debug
|
||||
DEBUG = -dDEBUG=1 -dDEBUGBUILD
|
||||
@@ -83,169 +90,162 @@ CFLAGS += -dWANT_IDN_PROTOTYPES
|
||||
!ifdef %zlib_root
|
||||
ZLIB_ROOT = $(%zlib_root)
|
||||
!else
|
||||
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.8
|
||||
ZLIB_ROOT = ../../zlib-1.2.8
|
||||
!endif
|
||||
|
||||
!ifdef %libssh2_root
|
||||
LIBSSH2_ROOT = $(%libssh2_root)
|
||||
!else
|
||||
LIBSSH2_ROOT = ..$(DS)..$(DS)libssh2-1.4.3
|
||||
LIBSSH2_ROOT = ../../libssh2-1.4.3
|
||||
!endif
|
||||
|
||||
!ifdef %librtmp_root
|
||||
LIBRTMP_ROOT = $(%librtmp_root)
|
||||
!else
|
||||
LIBRTMP_ROOT = ..$(DS)..$(DS)rtmpdump-2.3
|
||||
LIBRTMP_ROOT = ../../rtmpdump-2.3
|
||||
!endif
|
||||
|
||||
!ifdef %openssl_root
|
||||
OPENSSL_ROOT = $(%openssl_root)
|
||||
!else
|
||||
OPENSSL_ROOT = ..$(DS)..$(DS)openssl-0.9.8y
|
||||
OPENSSL_ROOT = ../../openssl-0.9.8y
|
||||
!endif
|
||||
|
||||
!ifdef %ares_root
|
||||
ARES_ROOT = $(%ares_root)
|
||||
!else
|
||||
ARES_ROOT = ..$(DS)ares
|
||||
ARES_ROOT = ../ares
|
||||
!endif
|
||||
|
||||
!ifdef %use_zlib
|
||||
CFLAGS += -dHAVE_ZLIB_H -dHAVE_LIBZ -I$(ZLIB_ROOT)
|
||||
CFLAGS += -dHAVE_ZLIB_H -dHAVE_LIBZ -I"$(ZLIB_ROOT)"
|
||||
!endif
|
||||
|
||||
!ifdef %use_rtmp
|
||||
CFLAGS += -dUSE_LIBRTMP -I$(LIBRTMP_ROOT)
|
||||
CFLAGS += -dUSE_LIBRTMP -I"$(LIBRTMP_ROOT)"
|
||||
!endif
|
||||
|
||||
!ifdef %use_ssh2
|
||||
CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H -I$(LIBSSH2_ROOT)$(DS)include -I$(LIBSSH2_ROOT)$(DS)win32
|
||||
CFLAGS += -DUSE_LIBSSH2 -DHAVE_LIBSSH2_H -I"$(LIBSSH2_ROOT)/include" -I"$(LIBSSH2_ROOT)/win32"
|
||||
!endif
|
||||
|
||||
!ifdef %use_ssl
|
||||
CFLAGS += -wcd=138 -dUSE_OPENSSL -dUSE_SSLEAY -I$(OPENSSL_ROOT)$(DS)inc32
|
||||
CFLAGS += -wcd=138 -dUSE_OPENSSL -dUSE_SSLEAY -I"$(OPENSSL_ROOT)/inc32"
|
||||
!endif
|
||||
|
||||
!ifdef %use_ares
|
||||
CFLAGS += -dUSE_ARES -I$(ARES_ROOT)
|
||||
CFLAGS += -dUSE_ARES -I"$(ARES_ROOT)"
|
||||
!endif
|
||||
|
||||
!ifdef %use_watt32
|
||||
CFLAGS += -dUSE_WATT32 -I$(%watt_root)$(DS)inc
|
||||
CFLAGS += -dUSE_WATT32 -I"$(%watt_root)/inc"
|
||||
!endif
|
||||
|
||||
OBJ_BASE = WC_Win32.obj
|
||||
LINK_ARG = $(OBJ_BASE)$(DS)dyn$(DS)wlink.arg
|
||||
LIB_ARG = $(OBJ_BASE)$(DS)stat$(DS)wlib.arg
|
||||
|
||||
# In order to process Makefile.inc wmake must be called with -u switch!
|
||||
!ifndef %MAKEFLAGS
|
||||
!error You MUST call wmake with the -u switch!
|
||||
!if $(__VERSION__) > 1290
|
||||
OBJ_STAT = $(OBJ_BASE)/stat
|
||||
OBJ_DYN = $(OBJ_BASE)/dyn
|
||||
!else ifdef __UNIX__
|
||||
OBJ_STAT = $(OBJ_BASE)/stat
|
||||
OBJ_DYN = $(OBJ_BASE)/dyn
|
||||
!else
|
||||
OBJ_STAT = $(OBJ_BASE)\stat
|
||||
OBJ_DYN = $(OBJ_BASE)\dyn
|
||||
!endif
|
||||
|
||||
LINK_ARG = $(OBJ_DYN)/wlink.arg
|
||||
LIB_ARG = $(OBJ_STAT)/wlib.arg
|
||||
|
||||
!include Makefile.inc
|
||||
!endif
|
||||
|
||||
OBJS = $(CSOURCES:.c=.obj)
|
||||
!ifdef __LINUX__
|
||||
OBJS = $OBJ_DIR/$(OBJS: = $OBJ_DIR/)
|
||||
OBJS1 = ./$(CSOURCES:.c=.obj)
|
||||
OBJS2 = $(OBJS1:vtls/=)
|
||||
OBJS3 = $(OBJS2: = ./)
|
||||
OBJS_STAT = $(OBJS3:./=$(OBJ_STAT)/)
|
||||
OBJS_DYN = $(OBJS3:./=$(OBJ_DYN)/)
|
||||
|
||||
!else
|
||||
OBJS = $OBJ_DIR\$(OBJS: = $OBJ_DIR\)
|
||||
!endif
|
||||
CURLBUILDH = ../include/curl/curlbuild.h
|
||||
RESOURCE = $(OBJ_DYN)/libcurl.res
|
||||
|
||||
#
|
||||
# Use $(OBJS) as a template to generate $(OBJS_STAT) and $(OBJS_DYN).
|
||||
#
|
||||
OBJ_DIR = $(OBJ_BASE)$(DS)stat
|
||||
OBJS_STAT = $+ $(OBJS) $-
|
||||
DIRS = $(OBJ_BASE) $(OBJ_BASE)/stat $(OBJ_BASE)/dyn
|
||||
|
||||
OBJ_DIR = $(OBJ_BASE)$(DS)dyn
|
||||
OBJS_DYN = $+ $(OBJS) $-
|
||||
.c : vtls
|
||||
|
||||
CURLBUILDH = ..$(DS)include$(DS)curl$(DS)curlbuild.h
|
||||
RESOURCE = $(OBJ_BASE)$(DS)dyn$(DS)libcurl.res
|
||||
|
||||
all: $(CURLBUILDH) $(OBJ_BASE) $(TARGETS) .SYMBOLIC
|
||||
all: $(CURLBUILDH) $(DIRS) $(TARGETS) .SYMBOLIC
|
||||
@echo Welcome to libcurl
|
||||
|
||||
clean: .SYMBOLIC
|
||||
-$(RM) $(OBJS_STAT)
|
||||
-$(RM) $(OBJS_DYN)
|
||||
-$(RM) $(RESOURCE) $(LINK_ARG) $(LIB_ARG)
|
||||
-rm -f $(OBJS_STAT)
|
||||
-rm -f $(OBJS_DYN)
|
||||
-rm -f $(RESOURCE) $(LINK_ARG) $(LIB_ARG)
|
||||
|
||||
vclean distclean: clean .SYMBOLIC
|
||||
-$(RM) $(TARGETS) $(LIBNAME).map $(LIBNAME).sym
|
||||
-$(RD) $(OBJ_BASE)$(DS)stat
|
||||
-$(RD) $(OBJ_BASE)$(DS)dyn
|
||||
-rm -f $(TARGETS) $(LIBNAME).map $(LIBNAME).sym
|
||||
-$(RD) $(OBJ_STAT)
|
||||
-$(RD) $(OBJ_DYN)
|
||||
-$(RD) $(OBJ_BASE)
|
||||
|
||||
$(OBJ_BASE):
|
||||
$(DIRS):
|
||||
-$(MD) $^@
|
||||
-$(MD) $^@$(DS)stat
|
||||
-$(MD) $^@$(DS)dyn
|
||||
|
||||
$(CURLBUILDH): .EXISTSONLY
|
||||
$(CP) $^@.dist $^@
|
||||
|
||||
$(LIBNAME).dll: $(OBJS_DYN) $(RESOURCE) $(LINK_ARG)
|
||||
$(LD) name $^@ @$]@
|
||||
|
||||
$(LIBNAME).lib: $(OBJS_STAT) $(LIB_ARG)
|
||||
$(AR) -q -b -c $^@ @$]@
|
||||
|
||||
.ERASE
|
||||
$(RESOURCE): libcurl.rc
|
||||
$(RC) $(DEBUG) -q -r -zm -bt=nt -I..$(DS)include $(SYS_INCL) $[@ -fo=$^@
|
||||
|
||||
.ERASE
|
||||
.c{$(OBJ_BASE)$(DS)dyn}.obj:
|
||||
$(CC) $(CFLAGS) -bd -br $[@ -fo=$^@
|
||||
|
||||
.ERASE
|
||||
.c{$(OBJ_BASE)$(DS)stat}.obj:
|
||||
$(CC) $(CFLAGS) -DCURL_STATICLIB $[@ -fo=$^@
|
||||
|
||||
$(LINK_ARG): $(__MAKEFILES__)
|
||||
%create $^@
|
||||
@%append $^@ system nt dll
|
||||
@%append $^@ file { $(OBJS_DYN) }
|
||||
$(LIBNAME).dll: $(OBJS_DYN) $(RESOURCE) $(__MAKEFILES__)
|
||||
%create $(LINK_ARG)
|
||||
@%append $(LINK_ARG) system nt dll
|
||||
!ifdef %debug
|
||||
@%append $^@ debug all
|
||||
@%append $^@ option symfile
|
||||
@%append $(LINK_ARG) debug all
|
||||
@%append $(LINK_ARG) option symfile
|
||||
!endif
|
||||
@%append $^@ option quiet, map, caseexact, eliminate, implib=$(LIBNAME)_imp.lib,
|
||||
@%append $^@ res=$(RESOURCE) libpath $(SYS_LIBS)
|
||||
@%append $^@ library wldap32.lib
|
||||
@%append $(LINK_ARG) option quiet, caseexact, eliminate
|
||||
@%append $(LINK_ARG) option map=$(OBJ_DYN)/$(LIBNAME).map
|
||||
@%append $(LINK_ARG) option implib=$(LIBNAME)_imp.lib
|
||||
@%append $(LINK_ARG) option res=$(RESOURCE)
|
||||
@for %f in ($(OBJS_DYN)) do @%append $(LINK_ARG) file %f
|
||||
@%append $(LINK_ARG) library wldap32.lib
|
||||
!ifdef %use_watt32
|
||||
@%append $^@ library $(%watt_root)$(DS)lib$(DS)wattcpw_imp.lib
|
||||
@%append $(LINK_ARG) library '$(%watt_root)/lib/wattcpw_imp.lib'
|
||||
!else
|
||||
@%append $^@ library ws2_32.lib
|
||||
@%append $(LINK_ARG) library ws2_32.lib
|
||||
!endif
|
||||
!ifdef %use_zlib
|
||||
@%append $^@ library $(ZLIB_ROOT)$(DS)zlib.lib
|
||||
@%append $(LINK_ARG) library '$(ZLIB_ROOT)/zlib.lib'
|
||||
!endif
|
||||
!ifdef %use_rtmp
|
||||
@%append $^@ library $(LIBRTMP_ROOT)$(DS)librtmp$(DS)librtmp.lib
|
||||
@%append $(LINK_ARG) library '$(LIBRTMP_ROOT)/librtmp/librtmp.lib'
|
||||
!endif
|
||||
!ifdef %use_ssh2
|
||||
@%append $^@ library $(LIBSSH2_ROOT)$(DS)win32$(DS)libssh2.lib
|
||||
@%append $(LINK_ARG) library '$(LIBSSH2_ROOT)/win32/libssh2.lib'
|
||||
!endif
|
||||
!ifdef %use_ssl
|
||||
@%append $^@ library $(OPENSSL_ROOT)$(DS)out32$(DS)libeay32.lib, $(OPENSSL_ROOT)$(DS)out32$(DS)ssleay32.lib
|
||||
@%append $(LINK_ARG) library '$(OPENSSL_ROOT)/out32/libeay32.lib'
|
||||
@%append $(LINK_ARG) library '$(OPENSSL_ROOT)/out32/ssleay32.lib'
|
||||
!endif
|
||||
!ifdef %use_ares
|
||||
@%append $^@ library $(ARES_ROOT)$(DS)cares.lib
|
||||
@%append $(LINK_ARG) library '$(ARES_ROOT)/cares.lib'
|
||||
!endif
|
||||
!ifdef %use_winidn
|
||||
! if $(__VERSION__) > 1290
|
||||
@%append $^@ library normaliz.lib
|
||||
@%append $(LINK_ARG) library normaliz.lib
|
||||
! else
|
||||
@%append $^@ import '_IdnToAscii@20' 'NORMALIZ.DLL'.'IdnToAscii'
|
||||
@%append $^@ import '_IdnToUnicode@20' 'NORMALIZ.DLL'.'IdnToUnicode'
|
||||
@%append $(LINK_ARG) import '_IdnToAscii@20' 'NORMALIZ.DLL'.'IdnToAscii'
|
||||
@%append $(LINK_ARG) import '_IdnToUnicode@20' 'NORMALIZ.DLL'.'IdnToUnicode'
|
||||
! endif
|
||||
!endif
|
||||
$(LD) name $^@ @$(LINK_ARG)
|
||||
|
||||
$(LIB_ARG): $(__MAKEFILES__)
|
||||
%create $^@
|
||||
@for %f in ($(OBJS_STAT)) do @%append $^@ +- %f
|
||||
$(LIBNAME).lib: $(OBJS_STAT)
|
||||
%create $(LIB_ARG)
|
||||
@for %f in ($<) do @%append $(LIB_ARG) +- %f
|
||||
$(AR) -q -b -c -pa $^@ @$(LIB_ARG)
|
||||
|
||||
$(RESOURCE): libcurl.rc
|
||||
$(RC) $(DEBUG) -q -r -zm -bt=nt -I"../include" $(SYS_INCL) $[@ -fo=$^@
|
||||
|
||||
.c{$(OBJ_DYN)}.obj:
|
||||
$(CC) $(CFLAGS) -bd -br $[@ -fo=$^@
|
||||
|
||||
.c{$(OBJ_STAT)}.obj:
|
||||
$(CC) $(CFLAGS) -DCURL_STATICLIB $[@ -fo=$^@
|
||||
|
||||
@@ -285,7 +285,7 @@ $(libcurl_dll_LIBRARY): $(libcurl_a_OBJECTS) $(RESOURCE) $(libcurl_dll_DEPENDENC
|
||||
$(libcurl_a_OBJECTS) $(RESOURCE) $(DLL_LIBS)
|
||||
|
||||
%.o: %.c $(PROOT)/include/curl/curlbuild.h
|
||||
$(CC) $(INCLUDES) $(CFLAGS) -c $<
|
||||
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
|
||||
|
||||
%.res: %.rc
|
||||
$(RC) $(RCFLAGS) $< -o $@
|
||||
|
||||
@@ -1,28 +1,63 @@
|
||||
|
||||
HTTP2 with libcurl
|
||||
|
||||
Spec: http://tools.ietf.org/html/draft-ietf-httpbis-http2-06
|
||||
Spec: http://tools.ietf.org/html/draft-ietf-httpbis-http2
|
||||
|
||||
Build prerequisites
|
||||
- nghttp2
|
||||
- OpenSSL or NSS or GnutTLS with a new enough version
|
||||
|
||||
nghttp2 (https://github.com/tatsuhiro-t/nghttp2)
|
||||
|
||||
We're depending on this 3rd party library for the actual low level protocol
|
||||
handling parts. The reason for this is that HTTP2 is much more complex at
|
||||
that layer than HTTP1.1 (which we implement on our own) and that nghttp2 is
|
||||
an already existing and well functional library.
|
||||
libcurl uses this 3rd party library for the low level protocol handling
|
||||
parts. The reason for this is that HTTP2 is much more complex at that layer
|
||||
than HTTP1.1 (which we implement on our own) and that nghttp2 is an already
|
||||
existing and well functional library.
|
||||
|
||||
Right now, nghttp2 implements http2 draft-09
|
||||
|
||||
We require at least version 0.3.0
|
||||
|
||||
Over an http:// URL
|
||||
|
||||
If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will include
|
||||
an upgrade header in the initial request to the host to allow upgrading to
|
||||
http2. Possibly introduce an option that will cause libcurl to fail if not
|
||||
possible to upgrade. Possibly introduce an option that makes libcurl use
|
||||
http2 at once over http://
|
||||
http2.
|
||||
|
||||
Possibly we can later introduce an option that will cause libcurl to fail if
|
||||
not possible to upgrade. Possibly we introduce an option that makes libcurl
|
||||
use http2 at once over http://
|
||||
|
||||
Over an https:// URL
|
||||
|
||||
If CURLOPT_HTTP_VERSION is set to CURL_HTTP_VERSION_2, libcurl will use ALPN
|
||||
(or NPN) to negotiate which protocol to continue with. Possibly introduce an
|
||||
option that will cause libcurl to fail if not possible to use http2.
|
||||
Consider options to explicitly disable ALPN and/or NPN.
|
||||
|
||||
ALPN is the TLS extension that http2 is expected to use. The NPN extension
|
||||
is for a similar purpose, was made prior to ALPN and is used for SPDY so
|
||||
early http2 servers are implemented using NPN before ALPN support is
|
||||
widespread.
|
||||
|
||||
SSL libs
|
||||
|
||||
The challenge is the ALPN and NPN support and all our different SSL
|
||||
backends. You may need a fairly updated SSL library version for it to
|
||||
provide the necessary TLS features. Right now we support:
|
||||
|
||||
OpenSSL: ALPN and NPN
|
||||
NSS: ALPN and NPN
|
||||
GnuTLS: ALPN
|
||||
|
||||
Applications
|
||||
|
||||
We hide http2's binary nature and convert received http2 traffic to headers
|
||||
in HTTP 1.1 style. This allows applications to work unmodified.
|
||||
|
||||
curl tool
|
||||
|
||||
curl offers the --http2 command line option to enable use of http2
|
||||
|
||||
To consider:
|
||||
|
||||
|
||||
@@ -570,11 +570,11 @@ static CURLcode trynextip(struct connectdata *conn,
|
||||
|
||||
if(ai) {
|
||||
rc = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
|
||||
conn->tempaddr[tempindex] = ai;
|
||||
if(rc == CURLE_COULDNT_CONNECT) {
|
||||
ai = ai->ai_next;
|
||||
continue;
|
||||
}
|
||||
conn->tempaddr[tempindex] = ai;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -235,6 +235,14 @@ void Curl_http_ntlm_cleanup(struct connectdata *conn)
|
||||
#else
|
||||
(void)conn;
|
||||
#endif
|
||||
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
Curl_safefree(conn->ntlm.target_info);
|
||||
conn->ntlm.target_info_len = 0;
|
||||
|
||||
Curl_safefree(conn->proxyntlm.target_info);
|
||||
conn->proxyntlm.target_info_len = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* USE_NTLM */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -96,6 +96,9 @@
|
||||
#include "rawstr.h"
|
||||
#include "curl_memory.h"
|
||||
#include "curl_ntlm_core.h"
|
||||
#include "curl_md5.h"
|
||||
#include "curl_hmac.h"
|
||||
#include "warnless.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@@ -103,6 +106,10 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#define NTLM_HMAC_MD5_LEN (16)
|
||||
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
|
||||
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
/*
|
||||
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
|
||||
@@ -377,6 +384,30 @@ static void ascii_to_unicode_le(unsigned char *dest, const char *src,
|
||||
}
|
||||
}
|
||||
|
||||
static void ascii_uppercase_to_unicode_le(unsigned char *dest,
|
||||
const char *src, size_t srclen)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < srclen; i++) {
|
||||
dest[2 * i] = (unsigned char)(toupper(src[i]));
|
||||
dest[2 * i + 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void write32_le(const int value, unsigned char *buffer)
|
||||
{
|
||||
buffer[0] = (char)(value & 0x000000FF);
|
||||
buffer[1] = (char)((value & 0x0000FF00) >> 8);
|
||||
buffer[2] = (char)((value & 0x00FF0000) >> 16);
|
||||
buffer[3] = (char)((value & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
static void write64_le(const long long value, unsigned char *buffer)
|
||||
{
|
||||
write32_le((int)value, buffer);
|
||||
write32_le((int)(value >> 32), buffer + 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up nt hashed passwords
|
||||
*/
|
||||
@@ -431,6 +462,180 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* This returns the HMAC MD5 digest */
|
||||
CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
|
||||
const unsigned char *data, unsigned int datalen,
|
||||
unsigned char *output)
|
||||
{
|
||||
HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
|
||||
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Update the digest with the given challenge */
|
||||
Curl_HMAC_update(ctxt, data, datalen);
|
||||
|
||||
/* Finalise the digest */
|
||||
Curl_HMAC_final(ctxt, output);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
|
||||
* (uppercase UserName + Domain) as the data
|
||||
*/
|
||||
CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
|
||||
const char *domain, size_t domlen,
|
||||
unsigned char *ntlmhash,
|
||||
unsigned char *ntlmv2hash)
|
||||
{
|
||||
/* Unicode representation */
|
||||
size_t identity_len = (userlen + domlen) * 2;
|
||||
unsigned char *identity = malloc(identity_len);
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
if(!identity)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
ascii_uppercase_to_unicode_le(identity, user, userlen);
|
||||
ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
|
||||
|
||||
res = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
|
||||
ntlmv2hash);
|
||||
|
||||
Curl_safefree(identity);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_ntlm_core_mk_ntlmv2_resp()
|
||||
*
|
||||
* This creates the NTLMv2 response as set in the ntlm type-3 message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
|
||||
* challenge_client [in] - The client nonce (8 bytes)
|
||||
* ntlm [in] - The ntlm data struct being used to read TargetInfo
|
||||
and Server challenge received in the type-2 message
|
||||
* ntresp [out] - The address where a pointer to newly allocated
|
||||
* memory holding the NTLMv2 response.
|
||||
* ntresp_len [out] - The length of the output message.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
unsigned char *challenge_client,
|
||||
struct ntlmdata *ntlm,
|
||||
unsigned char **ntresp,
|
||||
unsigned int *ntresp_len)
|
||||
{
|
||||
/* NTLMv2 response structure :
|
||||
------------------------------------------------------------------------------
|
||||
0 HMAC MD5 16 bytes
|
||||
------BLOB--------------------------------------------------------------------
|
||||
16 Signature 0x01010000
|
||||
20 Reserved long (0x00000000)
|
||||
24 Timestamp LE, 64-bit signed value representing the number of
|
||||
tenths of a microsecond since January 1, 1601.
|
||||
32 Client Nonce 8 bytes
|
||||
40 Unknown 4 bytes
|
||||
44 Target Info N bytes (from the type-2 message)
|
||||
44+N Unknown 4 bytes
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
unsigned int len = 0;
|
||||
unsigned char *ptr = NULL;
|
||||
unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
|
||||
long long tw;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
/* Calculate the timestamp */
|
||||
#if defined(DEBUGBUILD)
|
||||
tw = 11644473600ULL * 10000000ULL;
|
||||
#else
|
||||
tw = ((long long)time(NULL) + 11644473600ULL) * 10000000ULL;
|
||||
#endif
|
||||
|
||||
/* Calculate the response len */
|
||||
len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
|
||||
|
||||
/* Allocate the response */
|
||||
ptr = malloc(len);
|
||||
if(!ptr)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
memset(ptr, 0, len);
|
||||
|
||||
/* Create the BLOB structure */
|
||||
snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
|
||||
NTLMv2_BLOB_SIGNATURE
|
||||
"%c%c%c%c", /* Reserved = 0 */
|
||||
0, 0, 0, 0);
|
||||
|
||||
write64_le(tw, ptr + 24);
|
||||
memcpy(ptr + 32, challenge_client, 8);
|
||||
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
|
||||
|
||||
/* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
|
||||
memcpy(ptr + 8, &ntlm->nonce[0], 8);
|
||||
res = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
|
||||
NTLMv2_BLOB_LEN + 8, hmac_output);
|
||||
if(res) {
|
||||
Curl_safefree(ptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Concatenate the HMAC MD5 output with the BLOB */
|
||||
memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
|
||||
|
||||
/* Return the response */
|
||||
*ntresp = ptr;
|
||||
*ntresp_len = len;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_ntlm_core_mk_lmv2_resp()
|
||||
*
|
||||
* This creates the LMv2 response as used in the ntlm type-3 message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
|
||||
* challenge_client [in] - The client nonce (8 bytes)
|
||||
* challenge_client [in] - The server challenge (8 bytes)
|
||||
* lmresp [out] - The LMv2 response (24 bytes)
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
|
||||
unsigned char *challenge_client,
|
||||
unsigned char *challenge_server,
|
||||
unsigned char *lmresp)
|
||||
{
|
||||
unsigned char data[16];
|
||||
unsigned char hmac_output[16];
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
memcpy(&data[0], challenge_server, 8);
|
||||
memcpy(&data[8], challenge_client, 8);
|
||||
|
||||
res = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
/* Concatenate the HMAC MD5 output with the client nonce */
|
||||
memcpy(lmresp, hmac_output, 16);
|
||||
memcpy(lmresp+16, challenge_client, 8);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* USE_NTRESPONSES */
|
||||
|
||||
#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -58,9 +58,30 @@ void Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
|
||||
unsigned char *lmbuffer /* 21 bytes */);
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
|
||||
const unsigned char *data, unsigned int datalen,
|
||||
unsigned char *output);
|
||||
|
||||
CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
|
||||
const char *password,
|
||||
unsigned char *ntbuffer /* 21 bytes */);
|
||||
|
||||
CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
|
||||
const char *domain, size_t domlen,
|
||||
unsigned char *ntlmhash,
|
||||
unsigned char *ntlmv2hash);
|
||||
|
||||
CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
unsigned char *challenge_client,
|
||||
struct ntlmdata *ntlm,
|
||||
unsigned char **ntresp,
|
||||
unsigned int *ntresp_len);
|
||||
|
||||
CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
|
||||
unsigned char *challenge_client,
|
||||
unsigned char *challenge_server,
|
||||
unsigned char *lmresp);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -158,6 +158,68 @@ static unsigned int readint_le(unsigned char *buf)
|
||||
return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
|
||||
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function converts from the little endian format used in the incoming
|
||||
* package to whatever endian format we're using natively. Argument is a
|
||||
* pointer to a 2 byte buffer.
|
||||
*/
|
||||
static unsigned int readshort_le(unsigned char *buf)
|
||||
{
|
||||
return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_ntlm_decode_type2_target()
|
||||
*
|
||||
* This is used to decode the "target info" in the ntlm type-2 message
|
||||
* received.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* data [in] - Pointer to the session handle
|
||||
* buffer [in] - The decoded base64 ntlm header of Type 2
|
||||
* size [in] - The input buffer size, atleast 32 bytes
|
||||
* ntlm [in] - Pointer to ntlm data struct being used and modified.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data,
|
||||
unsigned char *buffer,
|
||||
size_t size,
|
||||
struct ntlmdata *ntlm)
|
||||
{
|
||||
unsigned int target_info_len = 0;
|
||||
unsigned int target_info_offset = 0;
|
||||
|
||||
Curl_safefree(ntlm->target_info);
|
||||
ntlm->target_info_len = 0;
|
||||
|
||||
if(size >= 48) {
|
||||
target_info_len = readshort_le(&buffer[40]);
|
||||
target_info_offset = readint_le(&buffer[44]);
|
||||
if(target_info_len > 0) {
|
||||
if(((target_info_offset + target_info_len) > size) ||
|
||||
(target_info_offset < 48)) {
|
||||
infof(data, "NTLM handshake failure (bad type-2 message). "
|
||||
"Target Info Offset Len is set incorrect by the peer\n");
|
||||
return CURLE_REMOTE_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
ntlm->target_info = malloc(target_info_len);
|
||||
if(!ntlm->target_info)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
|
||||
ntlm->target_info_len = target_info_len;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -194,8 +256,8 @@ static unsigned int readint_le(unsigned char *buf)
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
|
||||
const char* header,
|
||||
struct ntlmdata* ntlm)
|
||||
const char *header,
|
||||
struct ntlmdata *ntlm)
|
||||
{
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
|
||||
@@ -257,6 +319,15 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
|
||||
ntlm->flags = readint_le(&buffer[20]);
|
||||
memcpy(ntlm->nonce, &buffer[24], 8);
|
||||
|
||||
if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
|
||||
error = Curl_ntlm_decode_type2_target(data, buffer, size, ntlm);
|
||||
if(error) {
|
||||
free(buffer);
|
||||
infof(data, "NTLM handshake failure (bad type-2 message)\n");
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
|
||||
ntlm_print_flags(stderr, ntlm->flags);
|
||||
@@ -292,8 +363,7 @@ void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm)
|
||||
#ifndef USE_WINDOWS_SSPI
|
||||
/* copy the source to the destination and fill in zeroes in every
|
||||
other destination byte! */
|
||||
static void unicodecpy(unsigned char *dest,
|
||||
const char *src, size_t length)
|
||||
static void unicodecpy(unsigned char *dest, const char *src, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < length; i++) {
|
||||
@@ -645,7 +715,10 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
unsigned char lmresp[24]; /* fixed-size */
|
||||
#if USE_NTRESPONSES
|
||||
int ntrespoff;
|
||||
unsigned int ntresplen = 24;
|
||||
unsigned char ntresp[24]; /* fixed-size */
|
||||
unsigned char *ptr_ntresp = &ntresp[0];
|
||||
unsigned char *ntlmv2resp = NULL;
|
||||
#endif
|
||||
bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
|
||||
char host[HOSTNAME_MAX + 1] = "";
|
||||
@@ -657,7 +730,7 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
size_t hostlen = 0;
|
||||
size_t userlen = 0;
|
||||
size_t domlen = 0;
|
||||
CURLcode res;
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
user = strchr(userp, '\\');
|
||||
if(!user)
|
||||
@@ -684,11 +757,45 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
hostlen = strlen(host);
|
||||
}
|
||||
|
||||
if(unicode) {
|
||||
domlen = domlen * 2;
|
||||
userlen = userlen * 2;
|
||||
hostlen = hostlen * 2;
|
||||
#if USE_NTRESPONSES
|
||||
if(ntlm->target_info_len) {
|
||||
unsigned char ntbuffer[0x18];
|
||||
unsigned char entropy[8];
|
||||
unsigned char ntlmv2hash[0x18];
|
||||
|
||||
#if defined(DEBUGBUILD)
|
||||
/* Use static client nonce in debug (Test Suite) builds */
|
||||
memcpy(entropy, "12345678", sizeof(entropy));
|
||||
#else
|
||||
/* Create an 8 byte random client nonce */
|
||||
Curl_ssl_random(data, entropy, sizeof(entropy));
|
||||
#endif
|
||||
|
||||
res = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
res = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
|
||||
ntbuffer, ntlmv2hash);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
/* LMv2 response */
|
||||
res = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, &ntlm->nonce[0],
|
||||
lmresp);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
/* NTLMv2 response */
|
||||
res = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, ntlm, &ntlmv2resp,
|
||||
&ntresplen);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
ptr_ntresp = ntlmv2resp;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#if USE_NTLM2SESSION
|
||||
/* We don't support NTLM2 if we don't have USE_NTRESPONSES */
|
||||
@@ -718,9 +825,11 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
if(CURLE_OUT_OF_MEMORY ==
|
||||
Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
|
||||
|
||||
/* End of NTLM2 Session code */
|
||||
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -745,10 +854,16 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
* See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
|
||||
}
|
||||
|
||||
if(unicode) {
|
||||
domlen = domlen * 2;
|
||||
userlen = userlen * 2;
|
||||
hostlen = hostlen * 2;
|
||||
}
|
||||
|
||||
lmrespoff = 64; /* size of the message header */
|
||||
#if USE_NTRESPONSES
|
||||
ntrespoff = lmrespoff + 0x18;
|
||||
domoff = ntrespoff + 0x18;
|
||||
domoff = ntrespoff + ntresplen;
|
||||
#else
|
||||
domoff = lmrespoff + 0x18;
|
||||
#endif
|
||||
@@ -807,8 +922,8 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
0x0, 0x0,
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
SHORTPAIR(0x18), /* NT-response length, twice */
|
||||
SHORTPAIR(0x18),
|
||||
SHORTPAIR(ntresplen), /* NT-response length, twice */
|
||||
SHORTPAIR(ntresplen),
|
||||
SHORTPAIR(ntrespoff),
|
||||
0x0, 0x0,
|
||||
#else
|
||||
@@ -854,17 +969,19 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data,
|
||||
});
|
||||
|
||||
#if USE_NTRESPONSES
|
||||
if(size < (NTLM_BUFSIZE - 0x18)) {
|
||||
if(size < (NTLM_BUFSIZE - ntresplen)) {
|
||||
DEBUGASSERT(size == (size_t)ntrespoff);
|
||||
memcpy(&ntlmbuf[size], ntresp, 0x18);
|
||||
size += 0x18;
|
||||
memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
|
||||
size += ntresplen;
|
||||
}
|
||||
|
||||
DEBUG_OUT({
|
||||
fprintf(stderr, "\n ntresp=");
|
||||
ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
|
||||
ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
|
||||
});
|
||||
|
||||
Curl_safefree(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
|
||||
|
||||
#endif
|
||||
|
||||
DEBUG_OUT({
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -46,6 +46,13 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
|
||||
const char* header,
|
||||
struct ntlmdata* ntlm);
|
||||
|
||||
/* This is to decode target info received in NTLM type-2 message */
|
||||
CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data,
|
||||
unsigned char* buffer,
|
||||
size_t size,
|
||||
struct ntlmdata* ntlm);
|
||||
|
||||
|
||||
/* This is to clean up the ntlm data structure */
|
||||
#ifdef USE_WINDOWS_SSPI
|
||||
void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm);
|
||||
|
||||
@@ -601,12 +601,14 @@ int netware_init(void);
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
|
||||
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
|
||||
#define USE_HTTP_NEGOTIATE
|
||||
#endif
|
||||
|
||||
/* Single point where USE_NTLM definition might be done */
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM) && \
|
||||
!defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || \
|
||||
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL)
|
||||
#define USE_NTLM
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -122,9 +122,8 @@ static char *unescape_word(struct SessionHandle *data, const char *inputbuff)
|
||||
dictp[olen++] = byte;
|
||||
}
|
||||
dictp[olen]=0;
|
||||
|
||||
free(newp);
|
||||
}
|
||||
free(newp);
|
||||
return dictp;
|
||||
}
|
||||
|
||||
|
||||
@@ -715,6 +715,15 @@ static CURLcode easy_transfer(CURLM *multi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure to return some kind of error if there was a multi problem */
|
||||
if(mcode) {
|
||||
return (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
|
||||
/* The other multi errors should never happen, so return
|
||||
something suitably generic */
|
||||
CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -196,9 +196,8 @@ CURLcode Curl_urldecode(struct SessionHandle *data,
|
||||
/* store output size */
|
||||
*olen = strindex;
|
||||
|
||||
if(ostring)
|
||||
/* store output string */
|
||||
*ostring = ns;
|
||||
/* store output string */
|
||||
*ostring = ns;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -1110,8 +1110,10 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file,
|
||||
|
||||
/* filename need be escaped */
|
||||
filename_escaped = malloc(strlen(filename)*2+1);
|
||||
if(!filename_escaped)
|
||||
if(!filename_escaped) {
|
||||
Curl_safefree(filebasename);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
p0 = filename_escaped;
|
||||
p1 = filename;
|
||||
while(*p1) {
|
||||
@@ -1227,7 +1229,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
result = AddFormDataf(&form, &size,
|
||||
"\r\nContent-Type: multipart/mixed,"
|
||||
"\r\nContent-Type: multipart/mixed;"
|
||||
" boundary=%s\r\n",
|
||||
fileboundary);
|
||||
if(result)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -23,11 +23,16 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
|
||||
defined(USE_GSKIT) || defined(USE_NSS)
|
||||
defined(USE_GSKIT)
|
||||
/* these backends use functions from this file */
|
||||
|
||||
#include "hostcheck.h"
|
||||
#include "rawstr.h"
|
||||
#include "inet_pton.h"
|
||||
|
||||
#include "curl_memory.h"
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/*
|
||||
* Match a hostname against a wildcard pattern.
|
||||
@@ -36,18 +41,50 @@
|
||||
*
|
||||
* We use the matching rule described in RFC6125, section 6.4.3.
|
||||
* http://tools.ietf.org/html/rfc6125#section-6.4.3
|
||||
*
|
||||
* In addition: ignore trailing dots in the host names and wildcards, so that
|
||||
* the names are used normalized. This is what the browsers do.
|
||||
*
|
||||
* Do not allow wildcard matching on IP numbers. There are apparently
|
||||
* certificates being used with an IP address in the CN field, thus making no
|
||||
* apparent distinction between a name and an IP. We need to detect the use of
|
||||
* an IP address and not wildcard match on such names.
|
||||
*
|
||||
* NOTE: hostmatch() gets called with copied buffers so that it can modify the
|
||||
* contents at will.
|
||||
*/
|
||||
|
||||
static int hostmatch(const char *hostname, const char *pattern)
|
||||
static int hostmatch(char *hostname, char *pattern)
|
||||
{
|
||||
const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
|
||||
int wildcard_enabled;
|
||||
size_t prefixlen, suffixlen;
|
||||
struct in_addr ignored;
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_in6 si6;
|
||||
#endif
|
||||
|
||||
/* normalize pattern and hostname by stripping off trailing dots */
|
||||
size_t len = strlen(hostname);
|
||||
if(hostname[len-1]=='.')
|
||||
hostname[len-1]=0;
|
||||
len = strlen(pattern);
|
||||
if(pattern[len-1]=='.')
|
||||
pattern[len-1]=0;
|
||||
|
||||
pattern_wildcard = strchr(pattern, '*');
|
||||
if(pattern_wildcard == NULL)
|
||||
return Curl_raw_equal(pattern, hostname) ?
|
||||
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
|
||||
|
||||
/* detect IP address as hostname and fail the match if so */
|
||||
if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
|
||||
return CURL_HOST_NOMATCH;
|
||||
#ifdef ENABLE_IPV6
|
||||
else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
|
||||
return CURL_HOST_NOMATCH;
|
||||
#endif
|
||||
|
||||
/* We require at least 2 dots in pattern to avoid too wide wildcard
|
||||
match. */
|
||||
wildcard_enabled = 1;
|
||||
@@ -82,16 +119,26 @@ static int hostmatch(const char *hostname, const char *pattern)
|
||||
|
||||
int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
|
||||
{
|
||||
char *matchp;
|
||||
char *hostp;
|
||||
int res = 0;
|
||||
if(!match_pattern || !*match_pattern ||
|
||||
!hostname || !*hostname) /* sanity check */
|
||||
return 0;
|
||||
;
|
||||
else {
|
||||
matchp = strdup(match_pattern);
|
||||
if(matchp) {
|
||||
hostp = strdup(hostname);
|
||||
if(hostp) {
|
||||
if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
|
||||
res= 1;
|
||||
free(hostp);
|
||||
}
|
||||
free(matchp);
|
||||
}
|
||||
}
|
||||
|
||||
if(Curl_raw_equal(hostname, match_pattern)) /* trivial case */
|
||||
return 1;
|
||||
|
||||
if(hostmatch(hostname,match_pattern) == CURL_HOST_MATCH)
|
||||
return 1;
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT or NSS */
|
||||
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */
|
||||
|
||||
117
lib/http.c
117
lib/http.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -145,7 +145,7 @@ const struct Curl_handler Curl_handler_https = {
|
||||
ZERO_NULL, /* readwrite */
|
||||
PORT_HTTPS, /* defport */
|
||||
CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */
|
||||
PROTOPT_SSL /* flags */
|
||||
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1056,6 +1056,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
if(conn->handler->flags & PROTOPT_SSL) {
|
||||
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
|
||||
when we speak HTTPS, as if only a fraction of it is sent now, this data
|
||||
@@ -1360,8 +1361,8 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
|
||||
#endif
|
||||
|
||||
#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_DARWINSSL)
|
||||
/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only.
|
||||
defined(USE_DARWINSSL) || defined(USE_POLARSSL)
|
||||
/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
|
||||
It should be made to query the generic SSL layer instead. */
|
||||
static int https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
@@ -1492,6 +1493,10 @@ static CURLcode expect100(struct SessionHandle *data,
|
||||
const char *ptr;
|
||||
data->state.expect100header = FALSE; /* default to false unless it is set
|
||||
to TRUE below */
|
||||
if(conn->httpversion == 20) {
|
||||
/* We don't use Expect in HTTP2 */
|
||||
return CURLE_OK;
|
||||
}
|
||||
if(use_http_1_1plus(data, conn)) {
|
||||
/* if not doing HTTP 1.0 or disabled explicitly, we add a Expect:
|
||||
100-continue to the headers which actually speeds up post operations
|
||||
@@ -1668,6 +1673,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
the rest of the request in the PERFORM phase. */
|
||||
*done = TRUE;
|
||||
|
||||
switch (conn->negnpn) {
|
||||
case NPN_HTTP2_DRAFT09:
|
||||
infof(data, "http, we have to use HTTP-draft-09/2\n");
|
||||
Curl_http2_init(conn);
|
||||
Curl_http2_switched(conn);
|
||||
break;
|
||||
case NPN_HTTP1_1:
|
||||
/* continue with HTTP/1.1 when explicitly requested */
|
||||
break;
|
||||
default:
|
||||
/* and as fallback */
|
||||
break;
|
||||
}
|
||||
|
||||
http = data->req.protop;
|
||||
|
||||
if(!data->state.this_is_a_follow) {
|
||||
@@ -1782,35 +1801,40 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
}
|
||||
#endif
|
||||
|
||||
ptr = Curl_checkheaders(data, "Transfer-Encoding:");
|
||||
if(ptr) {
|
||||
/* Some kind of TE is requested, check if 'chunked' is chosen */
|
||||
data->req.upload_chunky =
|
||||
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
|
||||
}
|
||||
if(conn->httpversion == 20)
|
||||
/* In HTTP2 forbids Transfer-Encoding: chunked */
|
||||
ptr = NULL;
|
||||
else {
|
||||
if((conn->handler->protocol&CURLPROTO_HTTP) &&
|
||||
data->set.upload &&
|
||||
(data->set.infilesize == -1)) {
|
||||
if(conn->bits.authneg)
|
||||
/* don't enable chunked during auth neg */
|
||||
;
|
||||
else if(use_http_1_1plus(data, conn)) {
|
||||
/* HTTP, upload, unknown file size and not HTTP 1.0 */
|
||||
data->req.upload_chunky = TRUE;
|
||||
}
|
||||
else {
|
||||
failf(data, "Chunky upload is not supported by HTTP 1.0");
|
||||
return CURLE_UPLOAD_FAILED;
|
||||
}
|
||||
ptr = Curl_checkheaders(data, "Transfer-Encoding:");
|
||||
if(ptr) {
|
||||
/* Some kind of TE is requested, check if 'chunked' is chosen */
|
||||
data->req.upload_chunky =
|
||||
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
|
||||
}
|
||||
else {
|
||||
/* else, no chunky upload */
|
||||
data->req.upload_chunky = FALSE;
|
||||
}
|
||||
if((conn->handler->protocol&CURLPROTO_HTTP) &&
|
||||
data->set.upload &&
|
||||
(data->set.infilesize == -1)) {
|
||||
if(conn->bits.authneg)
|
||||
/* don't enable chunked during auth neg */
|
||||
;
|
||||
else if(use_http_1_1plus(data, conn)) {
|
||||
/* HTTP, upload, unknown file size and not HTTP 1.0 */
|
||||
data->req.upload_chunky = TRUE;
|
||||
}
|
||||
else {
|
||||
failf(data, "Chunky upload is not supported by HTTP 1.0");
|
||||
return CURLE_UPLOAD_FAILED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* else, no chunky upload */
|
||||
data->req.upload_chunky = FALSE;
|
||||
}
|
||||
|
||||
if(data->req.upload_chunky)
|
||||
te = "Transfer-Encoding: chunked\r\n";
|
||||
if(data->req.upload_chunky)
|
||||
te = "Transfer-Encoding: chunked\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
Curl_safefree(conn->allocptr.host);
|
||||
@@ -2176,7 +2200,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
(data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
|
||||
/* append HTTP2 updrade magic stuff to the HTTP request if it isn't done
|
||||
over SSL */
|
||||
result = Curl_http2_request(req_buffer, conn);
|
||||
result = Curl_http2_request_upgrade(req_buffer, conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -2450,7 +2474,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
|
||||
if(data->set.postfields) {
|
||||
|
||||
if(!data->state.expect100header &&
|
||||
/* In HTTP2, we send request body in DATA frame regardless of
|
||||
its size. */
|
||||
if(conn->httpversion != 20 &&
|
||||
!data->state.expect100header &&
|
||||
(postsize < MAX_INITIAL_POST_SIZE)) {
|
||||
/* if we don't use expect: 100 AND
|
||||
postsize is less than MAX_INITIAL_POST_SIZE
|
||||
@@ -2872,10 +2899,27 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
k->header = TRUE;
|
||||
k->headerline = 0; /* restart the header line counter */
|
||||
|
||||
/* if we did wait for this do enable write now! */
|
||||
if(k->exp100) {
|
||||
k->exp100 = EXP100_SEND_DATA;
|
||||
k->keepon |= KEEP_SEND;
|
||||
/* "A user agent MAY ignore unexpected 1xx status responses." */
|
||||
switch(k->httpcode) {
|
||||
case 100:
|
||||
/* if we did wait for this do enable write now! */
|
||||
if(k->exp100) {
|
||||
k->exp100 = EXP100_SEND_DATA;
|
||||
k->keepon |= KEEP_SEND;
|
||||
}
|
||||
break;
|
||||
case 101:
|
||||
/* Switching Protocols */
|
||||
if(k->upgr101 == UPGR101_REQUESTED) {
|
||||
infof(data, "Received 101\n");
|
||||
k->upgr101 = UPGR101_RECEIVED;
|
||||
|
||||
/* switch to http2 now */
|
||||
Curl_http2_switched(conn);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -3370,7 +3414,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
|
||||
|
||||
}
|
||||
else if(checkprefix("Content-Encoding:", k->p) &&
|
||||
data->set.str[STRING_ENCODING]) {
|
||||
(data->set.str[STRING_ENCODING] ||
|
||||
conn->httpversion == 20)) {
|
||||
/*
|
||||
* Process Content-Encoding. Look for the values: identity,
|
||||
* gzip, deflate, compress, x-gzip and x-compress. x-gzip and
|
||||
|
||||
30
lib/http.h
30
lib/http.h
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -149,9 +149,37 @@ struct HTTP {
|
||||
points to an allocated send_buffer struct */
|
||||
};
|
||||
|
||||
typedef int (*sending)(void); /* Curl_send */
|
||||
typedef int (*recving)(void); /* Curl_recv */
|
||||
|
||||
struct http_conn {
|
||||
#ifdef USE_NGHTTP2
|
||||
#define H2_BINSETTINGS_LEN 80
|
||||
nghttp2_session *h2;
|
||||
uint8_t binsettings[H2_BINSETTINGS_LEN];
|
||||
size_t binlen; /* length of the binsettings data */
|
||||
char *mem; /* points to a buffer in memory to store */
|
||||
size_t len; /* size of the buffer 'mem' points to */
|
||||
bool bodystarted;
|
||||
sending send_underlying; /* underlying send Curl_send callback */
|
||||
recving recv_underlying; /* underlying recv Curl_recv callback */
|
||||
bool closed; /* TRUE on HTTP2 stream close */
|
||||
Curl_send_buffer *header_recvbuf; /* store response headers */
|
||||
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf
|
||||
fed into upper layer */
|
||||
int32_t stream_id; /* stream we are interested in */
|
||||
const uint8_t *data; /* pointer to data chunk, received in
|
||||
on_data_chunk */
|
||||
size_t datalen; /* the number of bytes left in data */
|
||||
char *inbuf; /* buffer to receive data from underlying socket */
|
||||
/* We need separate buffer for transmission and reception because we
|
||||
may call nghttp2_session_send() after the
|
||||
nghttp2_session_mem_recv() but mem buffer is still not full. In
|
||||
this case, we wrongly sends the content of mem buffer if we share
|
||||
them for both cases. */
|
||||
const uint8_t *upload_mem; /* points to a buffer to read from */
|
||||
size_t upload_len; /* size of the buffer 'upload_mem' points to */
|
||||
size_t upload_left; /* number of bytes left to upload */
|
||||
#else
|
||||
int unused; /* prevent a compiler warning */
|
||||
#endif
|
||||
|
||||
773
lib/http2.c
773
lib/http2.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -33,10 +33,113 @@
|
||||
#include "sendf.h"
|
||||
#include "curl_base64.h"
|
||||
#include "curl_memory.h"
|
||||
#include "rawstr.h"
|
||||
#include "multiif.h"
|
||||
|
||||
/* include memdebug.h last */
|
||||
#include "memdebug.h"
|
||||
|
||||
#if (NGHTTP2_VERSION_NUM < 0x000300)
|
||||
#error too old nghttp2 version, upgrade!
|
||||
#endif
|
||||
|
||||
static int http2_perform_getsock(const struct connectdata *conn,
|
||||
curl_socket_t *sock, /* points to
|
||||
numsocks
|
||||
number of
|
||||
sockets */
|
||||
int numsocks)
|
||||
{
|
||||
const struct http_conn *httpc = &conn->proto.httpc;
|
||||
int bitmap = GETSOCK_BLANK;
|
||||
(void)numsocks;
|
||||
|
||||
/* TODO We should check underlying socket state if it is SSL socket
|
||||
because of renegotiation. */
|
||||
sock[0] = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(nghttp2_session_want_read(httpc->h2))
|
||||
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
|
||||
|
||||
if(nghttp2_session_want_write(httpc->h2))
|
||||
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static int http2_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock, /* points to numsocks
|
||||
number of sockets */
|
||||
int numsocks)
|
||||
{
|
||||
return http2_perform_getsock(conn, sock, numsocks);
|
||||
}
|
||||
|
||||
static CURLcode http2_disconnect(struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
{
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
(void)dead_connection;
|
||||
|
||||
infof(conn->data, "HTTP/2 DISCONNECT starts now\n");
|
||||
|
||||
nghttp2_session_del(httpc->h2);
|
||||
|
||||
Curl_safefree(httpc->header_recvbuf->buffer);
|
||||
Curl_safefree(httpc->header_recvbuf);
|
||||
|
||||
Curl_safefree(httpc->inbuf);
|
||||
|
||||
infof(conn->data, "HTTP/2 DISCONNECT done\n");
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTP2 handler interface. This isn't added to the general list of protocols
|
||||
* but will be used at run-time when the protocol is dynamically switched from
|
||||
* HTTP to HTTP2.
|
||||
*/
|
||||
const struct Curl_handler Curl_handler_http2 = {
|
||||
"HTTP2", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
ZERO_NULL, /* do_it */
|
||||
ZERO_NULL , /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
ZERO_NULL, /* connect_it */
|
||||
ZERO_NULL, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
http2_getsock, /* proto_getsock */
|
||||
http2_getsock, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
http2_perform_getsock, /* perform_getsock */
|
||||
http2_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
PORT_HTTP, /* defport */
|
||||
CURLPROTO_HTTP, /* protocol */
|
||||
PROTOPT_NONE /* flags */
|
||||
};
|
||||
|
||||
const struct Curl_handler Curl_handler_http2_ssl = {
|
||||
"HTTP2", /* scheme */
|
||||
ZERO_NULL, /* setup_connection */
|
||||
ZERO_NULL, /* do_it */
|
||||
ZERO_NULL , /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
ZERO_NULL, /* connect_it */
|
||||
ZERO_NULL, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
http2_getsock, /* proto_getsock */
|
||||
http2_getsock, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
http2_perform_getsock, /* perform_getsock */
|
||||
http2_disconnect, /* disconnect */
|
||||
ZERO_NULL, /* readwrite */
|
||||
PORT_HTTP, /* defport */
|
||||
CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */
|
||||
PROTOPT_SSL /* flags */
|
||||
};
|
||||
|
||||
/*
|
||||
* Store nghttp2 version info in this buffer, Prefix with a space. Return
|
||||
* total length written.
|
||||
@@ -57,68 +160,278 @@ static ssize_t send_callback(nghttp2_session *h2,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
ssize_t written;
|
||||
CURLcode rc =
|
||||
Curl_write(conn, conn->sock[0], data, length, &written);
|
||||
CURLcode rc;
|
||||
(void)h2;
|
||||
(void)flags;
|
||||
|
||||
if(rc) {
|
||||
rc = 0;
|
||||
written = ((Curl_send*)httpc->send_underlying)(conn, FIRSTSOCKET,
|
||||
data, length, &rc);
|
||||
|
||||
if(rc == CURLE_AGAIN) {
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
}
|
||||
|
||||
if(written == -1) {
|
||||
failf(conn->data, "Failed sending HTTP2 data");
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
else if(!written)
|
||||
|
||||
if(!written)
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_recv_callback type. Here we read data from
|
||||
* the network and write them in |buf|. The capacity of |buf| is |length|
|
||||
* bytes. Returns the number of bytes stored in |buf|. See the documentation
|
||||
* of nghttp2_recv_callback for the details.
|
||||
*/
|
||||
static ssize_t recv_callback(nghttp2_session *h2,
|
||||
uint8_t *buf, size_t length, int flags,
|
||||
static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
int rv;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
infof(conn->data, "on_frame_recv() was called with header %x\n",
|
||||
frame->hd.type);
|
||||
switch(frame->hd.type) {
|
||||
case NGHTTP2_HEADERS:
|
||||
if(frame->headers.cat != NGHTTP2_HCAT_RESPONSE)
|
||||
break;
|
||||
c->bodystarted = TRUE;
|
||||
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
||||
c->nread_header_recvbuf = c->len < c->header_recvbuf->size_used ?
|
||||
c->len : c->header_recvbuf->size_used;
|
||||
|
||||
memcpy(c->mem, c->header_recvbuf->buffer, c->nread_header_recvbuf);
|
||||
|
||||
c->mem += c->nread_header_recvbuf;
|
||||
c->len -= c->nread_header_recvbuf;
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE:
|
||||
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||
frame->hd.stream_id, NGHTTP2_CANCEL);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_invalid_frame_recv(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
nghttp2_error_code error_code, void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
infof(conn->data, "on_invalid_frame_recv() was called, error_code = %d\n",
|
||||
error_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const uint8_t *data, size_t len, void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
size_t nread;
|
||||
(void)session;
|
||||
(void)flags;
|
||||
(void)data;
|
||||
infof(conn->data, "on_data_chunk_recv() "
|
||||
"len = %u, stream = %x\n", len, stream_id);
|
||||
|
||||
if(stream_id != c->stream_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nread = c->len < len ? c->len : len;
|
||||
memcpy(c->mem, data, nread);
|
||||
|
||||
c->mem += nread;
|
||||
c->len -= nread;
|
||||
|
||||
infof(conn->data, "%zu data written\n", nread);
|
||||
|
||||
if(nread < len) {
|
||||
c->data = data + nread;
|
||||
c->datalen = len - nread;
|
||||
return NGHTTP2_ERR_PAUSE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int before_frame_send(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
ssize_t nread;
|
||||
CURLcode rc = Curl_read(conn, conn->sock[0], (char *)buf, length, &nread);
|
||||
(void)h2;
|
||||
(void)flags;
|
||||
|
||||
if(rc) {
|
||||
failf(conn->data, "Failed recving HTTP2 data");
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
infof(conn->data, "before_frame_send() was called\n");
|
||||
if(frame->hd.type == NGHTTP2_HEADERS &&
|
||||
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
|
||||
/* Get stream ID of our request */
|
||||
c->stream_id = frame->hd.stream_id;
|
||||
}
|
||||
if(!nread)
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
return 0;
|
||||
}
|
||||
static int on_frame_send(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
infof(conn->data, "on_frame_send() was called\n");
|
||||
return 0;
|
||||
}
|
||||
static int on_frame_not_send(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
int lib_error_code, void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
infof(conn->data, "on_frame_not_send() was called, lib_error_code = %d\n",
|
||||
lib_error_code);
|
||||
return 0;
|
||||
}
|
||||
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
nghttp2_error_code error_code, void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
(void)session;
|
||||
(void)stream_id;
|
||||
infof(conn->data, "on_stream_close() was called, error_code = %d\n",
|
||||
error_code);
|
||||
|
||||
return nread;
|
||||
if(stream_id != c->stream_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->closed = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_unknown_frame_recv(nghttp2_session *session,
|
||||
const uint8_t *head, size_t headlen,
|
||||
const uint8_t *payload, size_t payloadlen,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
(void)head;
|
||||
(void)headlen;
|
||||
(void)payload;
|
||||
(void)payloadlen;
|
||||
infof(conn->data, "on_unknown_frame_recv() was called\n");
|
||||
return 0;
|
||||
}
|
||||
static int on_begin_headers(nghttp2_session *session,
|
||||
const nghttp2_frame *frame, void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
infof(conn->data, "on_begin_headers() was called\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char STATUS[] = ":status";
|
||||
|
||||
/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
|
||||
static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
const uint8_t *name, size_t namelen,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
(void)session;
|
||||
(void)frame;
|
||||
|
||||
if(frame->hd.stream_id != c->stream_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(namelen == sizeof(":status") - 1 &&
|
||||
memcmp(STATUS, name, namelen) == 0) {
|
||||
snprintf(c->header_recvbuf->buffer, 13, "HTTP/2.0 %s", value);
|
||||
c->header_recvbuf->buffer[12] = '\r';
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* convert to a HTTP1-style header */
|
||||
infof(conn->data, "got header\n");
|
||||
Curl_add_buffer(c->header_recvbuf, name, namelen);
|
||||
Curl_add_buffer(c->header_recvbuf, ":", 1);
|
||||
Curl_add_buffer(c->header_recvbuf, value, valuelen);
|
||||
Curl_add_buffer(c->header_recvbuf, "\r\n", 2);
|
||||
}
|
||||
|
||||
return 0; /* 0 is successful */
|
||||
}
|
||||
|
||||
/*
|
||||
* This is all callbacks nghttp2 calls
|
||||
*/
|
||||
static const nghttp2_session_callbacks callbacks = {
|
||||
send_callback,
|
||||
recv_callback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
send_callback, /* nghttp2_send_callback */
|
||||
NULL, /* nghttp2_recv_callback */
|
||||
on_frame_recv, /* nghttp2_on_frame_recv_callback */
|
||||
on_invalid_frame_recv, /* nghttp2_on_invalid_frame_recv_callback */
|
||||
on_data_chunk_recv, /* nghttp2_on_data_chunk_recv_callback */
|
||||
before_frame_send, /* nghttp2_before_frame_send_callback */
|
||||
on_frame_send, /* nghttp2_on_frame_send_callback */
|
||||
on_frame_not_send, /* nghttp2_on_frame_not_send_callback */
|
||||
on_stream_close, /* nghttp2_on_stream_close_callback */
|
||||
on_unknown_frame_recv, /* nghttp2_on_unknown_frame_recv_callback */
|
||||
on_begin_headers, /* nghttp2_on_begin_headers_callback */
|
||||
on_header /* nghttp2_on_header_callback */
|
||||
#if NGHTTP2_VERSION_NUM >= 0x000400
|
||||
, NULL /* nghttp2_select_padding_callback */
|
||||
#endif
|
||||
};
|
||||
|
||||
static ssize_t data_source_read_callback(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
int *eof,
|
||||
nghttp2_data_source *source,
|
||||
void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
size_t nread;
|
||||
(void)session;
|
||||
(void)stream_id;
|
||||
(void)eof;
|
||||
(void)source;
|
||||
|
||||
nread = c->upload_len < length ? c->upload_len : length;
|
||||
if(nread > 0) {
|
||||
memcpy(buf, c->upload_mem, nread);
|
||||
c->upload_mem += nread;
|
||||
c->upload_len -= nread;
|
||||
c->upload_left -= nread;
|
||||
}
|
||||
|
||||
if(c->upload_left == 0)
|
||||
*eof = 1;
|
||||
else if(nread == 0)
|
||||
return NGHTTP2_ERR_DEFERRED;
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/*
|
||||
* The HTTP2 settings we send in the Upgrade request
|
||||
*/
|
||||
@@ -127,27 +440,53 @@ static nghttp2_settings_entry settings[] = {
|
||||
{ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
|
||||
};
|
||||
|
||||
/*
|
||||
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
|
||||
*/
|
||||
CURLcode Curl_http2_request(Curl_send_buffer *req,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
uint8_t binsettings[80];
|
||||
CURLcode result;
|
||||
ssize_t binlen;
|
||||
char *base64;
|
||||
size_t blen;
|
||||
#define H2_BUFSIZE 4096
|
||||
|
||||
/*
|
||||
* Initialize nghttp2 for a Curl connection
|
||||
*/
|
||||
CURLcode Curl_http2_init(struct connectdata *conn)
|
||||
{
|
||||
if(!conn->proto.httpc.h2) {
|
||||
int rc;
|
||||
conn->proto.httpc.inbuf = malloc(H2_BUFSIZE);
|
||||
if(conn->proto.httpc.inbuf == NULL)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* The nghttp2 session is not yet setup, do it */
|
||||
int rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
|
||||
&callbacks, &conn);
|
||||
rc = nghttp2_session_client_new(&conn->proto.httpc.h2,
|
||||
&callbacks, conn);
|
||||
if(rc) {
|
||||
failf(conn->data, "Couldn't initialize nghttp2!");
|
||||
return CURLE_OUT_OF_MEMORY; /* most likely at least */
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a request using http2
|
||||
*/
|
||||
CURLcode Curl_http2_send_request(struct connectdata *conn)
|
||||
{
|
||||
(void)conn;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
|
||||
*/
|
||||
CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result;
|
||||
ssize_t binlen;
|
||||
char *base64;
|
||||
size_t blen;
|
||||
struct SingleRequest *k = &conn->data->req;
|
||||
uint8_t *binsettings = conn->proto.httpc.binsettings;
|
||||
|
||||
Curl_http2_init(conn);
|
||||
|
||||
/* As long as we have a fixed set of settings, we don't have to dynamically
|
||||
* figure out the base64 strings since it'll always be the same. However,
|
||||
@@ -155,14 +494,14 @@ CURLcode Curl_http2_request(Curl_send_buffer *req,
|
||||
*/
|
||||
|
||||
/* this returns number of bytes it wrote */
|
||||
binlen = nghttp2_pack_settings_payload(binsettings,
|
||||
sizeof(binsettings),
|
||||
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
|
||||
settings,
|
||||
sizeof(settings)/sizeof(settings[0]));
|
||||
if(!binlen) {
|
||||
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
conn->proto.httpc.binlen = binlen;
|
||||
|
||||
result = Curl_base64_encode(conn->data, (const char *)binsettings, binlen,
|
||||
&base64, &blen);
|
||||
@@ -174,9 +513,335 @@ CURLcode Curl_http2_request(Curl_send_buffer *req,
|
||||
"Upgrade: %s\r\n"
|
||||
"HTTP2-Settings: %s\r\n",
|
||||
NGHTTP2_PROTO_VERSION_ID, base64);
|
||||
free(base64);
|
||||
Curl_safefree(base64);
|
||||
|
||||
k->upgr101 = UPGR101_REQUESTED;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
|
||||
* a regular CURLcode value.
|
||||
*/
|
||||
static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
{
|
||||
CURLcode rc;
|
||||
ssize_t rv;
|
||||
ssize_t nread;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
|
||||
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
|
||||
|
||||
if(httpc->closed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nullify here because we call nghttp2_session_send() and they
|
||||
might refer to the old buffer. */
|
||||
httpc->upload_mem = NULL;
|
||||
httpc->upload_len = 0;
|
||||
|
||||
if(httpc->bodystarted &&
|
||||
httpc->nread_header_recvbuf < httpc->header_recvbuf->size_used) {
|
||||
size_t left =
|
||||
httpc->header_recvbuf->size_used - httpc->nread_header_recvbuf;
|
||||
size_t ncopy = len < left ? len : left;
|
||||
memcpy(mem, httpc->header_recvbuf->buffer + httpc->nread_header_recvbuf,
|
||||
ncopy);
|
||||
httpc->nread_header_recvbuf += ncopy;
|
||||
return ncopy;
|
||||
}
|
||||
|
||||
if(httpc->data) {
|
||||
nread = len < httpc->datalen ? len : httpc->datalen;
|
||||
memcpy(mem, httpc->data, nread);
|
||||
|
||||
httpc->data += nread;
|
||||
httpc->datalen -= nread;
|
||||
|
||||
infof(conn->data, "%zu data written\n", nread);
|
||||
if(httpc->datalen == 0) {
|
||||
httpc->data = NULL;
|
||||
httpc->datalen = 0;
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
|
||||
conn->proto.httpc.mem = mem;
|
||||
conn->proto.httpc.len = len;
|
||||
|
||||
infof(conn->data, "http2_recv: %d bytes buffer\n",
|
||||
conn->proto.httpc.len);
|
||||
|
||||
rc = 0;
|
||||
nread = ((Curl_recv*)httpc->recv_underlying)(conn, FIRSTSOCKET,
|
||||
httpc->inbuf, H2_BUFSIZE, &rc);
|
||||
|
||||
if(rc == CURLE_AGAIN) {
|
||||
*err = rc;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(nread == -1) {
|
||||
failf(conn->data, "Failed receiving HTTP2 data");
|
||||
*err = rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
infof(conn->data, "nread=%zd\n", nread);
|
||||
rv = nghttp2_session_mem_recv(httpc->h2,
|
||||
(const uint8_t *)httpc->inbuf, nread);
|
||||
|
||||
if(nghttp2_is_fatal((int)rv)) {
|
||||
failf(conn->data, "nghttp2_session_mem_recv() returned %d:%s\n",
|
||||
rv, nghttp2_strerror((int)rv));
|
||||
*err = CURLE_RECV_ERROR;
|
||||
return 0;
|
||||
}
|
||||
infof(conn->data, "nghttp2_session_mem_recv() returns %zd\n", rv);
|
||||
/* Always send pending frames in nghttp2 session, because
|
||||
nghttp2_session_mem_recv() may queue new frame */
|
||||
rv = nghttp2_session_send(httpc->h2);
|
||||
if(rv != 0) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if(len != httpc->len) {
|
||||
return len - conn->proto.httpc.len;
|
||||
}
|
||||
/* If stream is closed, return 0 to signal the http routine to close
|
||||
the connection */
|
||||
if(httpc->closed) {
|
||||
return 0;
|
||||
}
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define MAKE_NV(k, v) \
|
||||
{ (uint8_t*)k, (uint8_t*)v, sizeof(k) - 1, sizeof(v) - 1 }
|
||||
|
||||
#define MAKE_NV2(k, v, vlen) \
|
||||
{ (uint8_t*)k, (uint8_t*)v, sizeof(k) - 1, vlen }
|
||||
|
||||
/* return number of received (decrypted) bytes */
|
||||
static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
const void *mem, size_t len, CURLcode *err)
|
||||
{
|
||||
/*
|
||||
* BIG TODO: Currently, we send request in this function, but this
|
||||
* function is also used to send request body. It would be nice to
|
||||
* add dedicated function for request.
|
||||
*/
|
||||
int rv;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
nghttp2_nv *nva;
|
||||
size_t nheader;
|
||||
size_t i;
|
||||
char *hdbuf = (char*)mem;
|
||||
char *end;
|
||||
nghttp2_data_provider data_prd;
|
||||
(void)sockindex;
|
||||
|
||||
infof(conn->data, "http2_send len=%zu\n", len);
|
||||
|
||||
if(httpc->stream_id != -1) {
|
||||
/* If stream_id != -1, we have dispatched request HEADERS, and now
|
||||
are going to send or sending request body in DATA frame */
|
||||
httpc->upload_mem = mem;
|
||||
httpc->upload_len = len;
|
||||
nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
|
||||
rv = nghttp2_session_send(httpc->h2);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
return len - httpc->upload_len;
|
||||
}
|
||||
|
||||
/* Calculate number of headers contained in [mem, mem + len) */
|
||||
/* Here, we assume the curl http code generate *correct* HTTP header
|
||||
field block */
|
||||
nheader = 0;
|
||||
for(i = 0; i < len; ++i) {
|
||||
if(hdbuf[i] == 0x0a) {
|
||||
++nheader;
|
||||
}
|
||||
}
|
||||
/* We counted additional 2 \n in the first and last line. We need 3
|
||||
new headers: :method, :path and :scheme. Therefore we need one
|
||||
more space. */
|
||||
nheader += 1;
|
||||
nva = malloc(sizeof(nghttp2_nv) * nheader);
|
||||
if(nva == NULL) {
|
||||
*err = CURLE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
/* Extract :method, :path from request line */
|
||||
end = strchr(hdbuf, ' ');
|
||||
nva[0].name = (unsigned char *)":method";
|
||||
nva[0].namelen = (uint16_t)strlen((char *)nva[0].name);
|
||||
nva[0].value = (unsigned char *)hdbuf;
|
||||
nva[0].valuelen = (uint16_t)(end - hdbuf);
|
||||
|
||||
hdbuf = end + 1;
|
||||
|
||||
end = strchr(hdbuf, ' ');
|
||||
nva[1].name = (unsigned char *)":path";
|
||||
nva[1].namelen = (uint16_t)strlen((char *)nva[1].name);
|
||||
nva[1].value = (unsigned char *)hdbuf;
|
||||
nva[1].valuelen = (uint16_t)(end - hdbuf);
|
||||
|
||||
nva[2].name = (unsigned char *)":scheme";
|
||||
nva[2].namelen = (uint16_t)strlen((char *)nva[2].name);
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
nva[2].value = (unsigned char *)"https";
|
||||
else
|
||||
nva[2].value = (unsigned char *)"http";
|
||||
nva[2].valuelen = (uint16_t)strlen((char *)nva[2].value);
|
||||
|
||||
hdbuf = strchr(hdbuf, 0x0a);
|
||||
++hdbuf;
|
||||
|
||||
for(i = 3; i < nheader; ++i) {
|
||||
end = strchr(hdbuf, ':');
|
||||
assert(end);
|
||||
if(end - hdbuf == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
|
||||
nva[i].name = (unsigned char *)":authority";
|
||||
nva[i].namelen = (uint16_t)strlen((char *)nva[i].name);
|
||||
}
|
||||
else {
|
||||
nva[i].name = (unsigned char *)hdbuf;
|
||||
nva[i].namelen = (uint16_t)(end - hdbuf);
|
||||
}
|
||||
hdbuf = end + 1;
|
||||
for(; *hdbuf == ' '; ++hdbuf);
|
||||
end = strchr(hdbuf, 0x0d);
|
||||
assert(end);
|
||||
nva[i].value = (unsigned char *)hdbuf;
|
||||
nva[i].valuelen = (uint16_t)(end - hdbuf);
|
||||
|
||||
hdbuf = end + 2;
|
||||
/* Inspect Content-Length header field and retrieve the request
|
||||
entity length so that we can set END_STREAM to the last DATA
|
||||
frame. */
|
||||
if(nva[i].namelen == 14 &&
|
||||
Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
|
||||
size_t j;
|
||||
for(j = 0; j < nva[i].valuelen; ++j) {
|
||||
httpc->upload_left *= 10;
|
||||
httpc->upload_left += nva[i].value[j] - '0';
|
||||
}
|
||||
infof(conn->data, "request content-length=%zu\n", httpc->upload_left);
|
||||
}
|
||||
}
|
||||
|
||||
switch(conn->data->set.httpreq) {
|
||||
case HTTPREQ_POST:
|
||||
case HTTPREQ_POST_FORM:
|
||||
case HTTPREQ_PUT:
|
||||
data_prd.read_callback = data_source_read_callback;
|
||||
data_prd.source.ptr = NULL;
|
||||
rv = nghttp2_submit_request(httpc->h2, 0, nva, nheader, &data_prd, NULL);
|
||||
break;
|
||||
default:
|
||||
rv = nghttp2_submit_request(httpc->h2, 0, nva, nheader, NULL, NULL);
|
||||
}
|
||||
|
||||
Curl_safefree(nva);
|
||||
|
||||
if(rv != 0) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = nghttp2_session_send(httpc->h2);
|
||||
|
||||
if(rv != 0) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(httpc->stream_id != -1) {
|
||||
/* If whole HEADERS frame was sent off to the underlying socket,
|
||||
the nghttp2 library calls data_source_read_callback. But only
|
||||
it found that no data available, so it deferred the DATA
|
||||
transmission. Which means that nghttp2_session_want_write()
|
||||
returns 0 on http2_perform_getsock(), which results that no
|
||||
writable socket check is performed. To workaround this, we
|
||||
issue nghttp2_session_resume_data() here to bring back DATA
|
||||
transmission from deferred state. */
|
||||
nghttp2_session_resume_data(httpc->h2, httpc->stream_id);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int Curl_http2_switched(struct connectdata *conn)
|
||||
{
|
||||
int rv;
|
||||
CURLcode rc;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
/* we are switched! */
|
||||
/* Don't know this is needed here at this moment. Original
|
||||
handler->flags is still useful. */
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
conn->handler = &Curl_handler_http2_ssl;
|
||||
else
|
||||
conn->handler = &Curl_handler_http2;
|
||||
|
||||
httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
|
||||
httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
|
||||
conn->recv[FIRSTSOCKET] = http2_recv;
|
||||
conn->send[FIRSTSOCKET] = http2_send;
|
||||
infof(conn->data, "We have switched to HTTP2\n");
|
||||
httpc->bodystarted = FALSE;
|
||||
httpc->closed = FALSE;
|
||||
httpc->header_recvbuf = Curl_add_buffer_init();
|
||||
httpc->nread_header_recvbuf = 0;
|
||||
httpc->data = NULL;
|
||||
httpc->datalen = 0;
|
||||
httpc->upload_left = 0;
|
||||
httpc->upload_mem = NULL;
|
||||
httpc->upload_len = 0;
|
||||
|
||||
conn->httpversion = 20;
|
||||
|
||||
/* Put place holder for status line */
|
||||
Curl_add_buffer(httpc->header_recvbuf, "HTTP/2.0 200\r\n", 14);
|
||||
|
||||
/* TODO: May get CURLE_AGAIN */
|
||||
rv = (int) ((Curl_send*)httpc->send_underlying)
|
||||
(conn, FIRSTSOCKET,
|
||||
NGHTTP2_CLIENT_CONNECTION_HEADER,
|
||||
NGHTTP2_CLIENT_CONNECTION_HEADER_LEN,
|
||||
&rc);
|
||||
assert(rv == 24);
|
||||
if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
|
||||
/* stream 1 is opened implicitly on upgrade */
|
||||
httpc->stream_id = 1;
|
||||
/* queue SETTINGS frame (again) */
|
||||
rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
|
||||
httpc->binlen, NULL);
|
||||
if(rv != 0) {
|
||||
failf(conn->data, "nghttp2_session_upgrade() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* stream ID is unknown at this point */
|
||||
httpc->stream_id = -1;
|
||||
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
|
||||
if(rv != 0) {
|
||||
failf(conn->data, "nghttp2_submit_settings() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
14
lib/http2.h
14
lib/http2.h
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -32,10 +32,16 @@
|
||||
*/
|
||||
int Curl_http2_ver(char *p, size_t len);
|
||||
|
||||
CURLcode Curl_http2_request(Curl_send_buffer *req,
|
||||
struct connectdata *conn);
|
||||
CURLcode Curl_http2_init(struct connectdata *conn);
|
||||
CURLcode Curl_http2_send_request(struct connectdata *conn);
|
||||
CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
||||
struct connectdata *conn);
|
||||
int Curl_http2_switched(struct connectdata *conn);
|
||||
#else /* USE_NGHTTP2 */
|
||||
#define Curl_http2_request(x,y) CURLE_OK
|
||||
#define Curl_http2_init(x)
|
||||
#define Curl_http2_send_request(x)
|
||||
#define Curl_http2_request_upgrade(x,y) CURLE_OK
|
||||
#define Curl_http2_switched(x)
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_HTTP2_H */
|
||||
|
||||
@@ -162,8 +162,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
}
|
||||
|
||||
ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16);
|
||||
if(errno == ERANGE)
|
||||
/* over or underflow is an error */
|
||||
if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE))
|
||||
/* overflow is an error */
|
||||
return CHUNKE_ILLEGAL_HEX;
|
||||
ch->state = CHUNK_LF; /* now wait for the CRLF */
|
||||
}
|
||||
@@ -361,4 +361,25 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
}
|
||||
return CHUNKE_OK;
|
||||
}
|
||||
|
||||
const char *Curl_chunked_strerror(CHUNKcode code)
|
||||
{
|
||||
switch (code) {
|
||||
default:
|
||||
return "OK";
|
||||
case CHUNKE_TOO_LONG_HEX:
|
||||
return "Too long hexadecimal number";
|
||||
case CHUNKE_ILLEGAL_HEX:
|
||||
return "Illegal or missing hexadecimal sequence";
|
||||
case CHUNKE_BAD_CHUNK:
|
||||
return "Malformed encoding found";
|
||||
case CHUNKE_WRITE_ERROR:
|
||||
return "Write error";
|
||||
case CHUNKE_BAD_ENCODING:
|
||||
return "Bad content-encoding found";
|
||||
case CHUNKE_OUT_OF_MEMORY:
|
||||
return "Out of memory";
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
@@ -72,12 +72,13 @@ typedef enum {
|
||||
CHUNKE_ILLEGAL_HEX,
|
||||
CHUNKE_BAD_CHUNK,
|
||||
CHUNKE_WRITE_ERROR,
|
||||
CHUNKE_STATE_ERROR,
|
||||
CHUNKE_BAD_ENCODING,
|
||||
CHUNKE_OUT_OF_MEMORY,
|
||||
CHUNKE_LAST
|
||||
} CHUNKcode;
|
||||
|
||||
const char *Curl_chunked_strerror(CHUNKcode code);
|
||||
|
||||
struct Curl_chunker {
|
||||
char hexbuffer[ MAXNUM_SIZE + 1];
|
||||
int hexindex;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -92,7 +92,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
|
||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
int sockindex,
|
||||
const char *hostname,
|
||||
unsigned short remote_port)
|
||||
int remote_port)
|
||||
{
|
||||
int subversion=0;
|
||||
struct SessionHandle *data=conn->data;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -26,7 +26,7 @@
|
||||
/* ftp can use this as well */
|
||||
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
||||
int tunnelsocket,
|
||||
const char *hostname, unsigned short remote_port);
|
||||
const char *hostname, int remote_port);
|
||||
|
||||
/* Default proxy timeout in milliseconds */
|
||||
#define PROXY_TIMEOUT (3600*1000)
|
||||
|
||||
20
lib/multi.c
20
lib/multi.c
@@ -317,6 +317,9 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
|
||||
multi->closure_handle->state.conn_cache = multi->conn_cache;
|
||||
|
||||
multi->max_pipeline_length = 5;
|
||||
|
||||
/* -1 means it not set by user, use the default value */
|
||||
multi->maxconnects = -1;
|
||||
return (CURLM *) multi;
|
||||
|
||||
error:
|
||||
@@ -551,9 +554,11 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
Curl_getoff_all_pipelines(data, data->easy_conn);
|
||||
}
|
||||
|
||||
Curl_wildcard_dtor(&data->wildcard);
|
||||
|
||||
/* as this was using a shared connection cache we clear the pointer
|
||||
to that since we're not part of that multi handle anymore */
|
||||
data->state.conn_cache = NULL;
|
||||
data->state.conn_cache = NULL;
|
||||
|
||||
/* change state without using multistate(), only to make singlesocket() do
|
||||
what we want */
|
||||
@@ -1019,6 +1024,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
if(CURLE_OK == data->result) {
|
||||
/* after init, go CONNECT */
|
||||
multistate(data, CURLM_STATE_CONNECT);
|
||||
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
||||
result = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
break;
|
||||
@@ -1030,7 +1036,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
|
||||
case CURLM_STATE_CONNECT:
|
||||
/* Connect. We want to get a connection identifier filled in. */
|
||||
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
||||
data->result = Curl_connect(data, &data->easy_conn,
|
||||
&async, &protocol_connect);
|
||||
if(CURLE_NO_CONNECTION_AVAILABLE == data->result) {
|
||||
@@ -1739,6 +1744,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
while(data) {
|
||||
CURLMcode result;
|
||||
struct WildcardData *wc = &data->wildcard;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(data->set.wildcardmatch) {
|
||||
if(!wc->filelist) {
|
||||
@@ -1748,9 +1754,11 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
|
||||
}
|
||||
}
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
do
|
||||
result = multi_runsingle(multi, now, data);
|
||||
while(CURLM_CALL_MULTI_PERFORM == result);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(data->set.wildcardmatch) {
|
||||
/* destruct wildcard structures if it is needed */
|
||||
@@ -2195,6 +2203,8 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
and just move on. */
|
||||
;
|
||||
else {
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
data = entry->easy;
|
||||
|
||||
if(data->magic != CURLEASY_MAGIC_NUMBER)
|
||||
@@ -2220,9 +2230,11 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
/* set socket event bitmask if they're not locked */
|
||||
data->easy_conn->cselect_bits = ev_bitmask;
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
do
|
||||
result = multi_runsingle(multi, now, data);
|
||||
while(CURLM_CALL_MULTI_PERFORM == result);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(data->easy_conn &&
|
||||
!(data->easy_conn->handler->flags & PROTOPT_DIRLOCK))
|
||||
@@ -2260,9 +2272,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||
do {
|
||||
/* the first loop lap 'data' can be NULL */
|
||||
if(data) {
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
do
|
||||
result = multi_runsingle(multi, now, data);
|
||||
while(CURLM_CALL_MULTI_PERFORM == result);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(CURLM_OK >= result)
|
||||
/* get the socket(s) and check if the state has been changed since
|
||||
|
||||
@@ -410,8 +410,10 @@ static int parsedate(const char *date, time_t *output)
|
||||
if(error)
|
||||
return PARSEDATE_FAIL;
|
||||
|
||||
#if LONG_MAX != INT_MAX
|
||||
if((lval > (long)INT_MAX) || (lval < (long)INT_MIN))
|
||||
return PARSEDATE_FAIL;
|
||||
#endif
|
||||
|
||||
val = curlx_sltosi(lval);
|
||||
|
||||
|
||||
@@ -201,11 +201,18 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
|
||||
char *port;
|
||||
struct site_blacklist_entry *entry;
|
||||
|
||||
entry = malloc(sizeof(struct site_blacklist_entry));
|
||||
|
||||
hostname = strdup(*sites);
|
||||
if(!hostname)
|
||||
if(!hostname) {
|
||||
Curl_llist_destroy(new_list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(struct site_blacklist_entry));
|
||||
if(!entry) {
|
||||
free(hostname);
|
||||
Curl_llist_destroy(new_list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
port = strchr(hostname, ':');
|
||||
if(port) {
|
||||
@@ -220,8 +227,11 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
|
||||
|
||||
entry->hostname = hostname;
|
||||
|
||||
if(!Curl_llist_insert_next(new_list, new_list->tail, entry))
|
||||
if(!Curl_llist_insert_next(new_list, new_list->tail, entry)) {
|
||||
site_blacklist_llist_dtor(NULL, entry);
|
||||
Curl_llist_destroy(new_list, NULL);
|
||||
return CURLM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
sites++;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -763,7 +763,7 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
|
||||
char *start;
|
||||
|
||||
/* Find the first non-space letter */
|
||||
start = header + 9;
|
||||
start = header + 8;
|
||||
while(*start && ISSPACE(*start))
|
||||
start++;
|
||||
|
||||
|
||||
39
lib/ssh.c
39
lib/ssh.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -328,6 +328,7 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
|
||||
/* This is the ONLY way to change SSH state! */
|
||||
static void state(struct connectdata *conn, sshstate nowstate)
|
||||
{
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
/* for debug purposes */
|
||||
static const char * const names[] = {
|
||||
@@ -387,10 +388,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
|
||||
"SSH_SESSION_FREE",
|
||||
"QUIT"
|
||||
};
|
||||
#endif
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
if(sshc->state != nowstate) {
|
||||
infof(conn->data, "SFTP %p state change from %s to %s\n",
|
||||
(void *)sshc, names[sshc->state], names[nowstate]);
|
||||
@@ -736,6 +734,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
result = ssh_check_fingerprint(conn);
|
||||
if(result == CURLE_OK)
|
||||
state(conn, SSH_AUTHLIST);
|
||||
/* ssh_check_fingerprint sets state appropriately on error */
|
||||
break;
|
||||
|
||||
case SSH_AUTHLIST:
|
||||
@@ -932,6 +931,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
infof(data, "Could not create agent object\n");
|
||||
|
||||
state(conn, SSH_AUTH_KEY_INIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1197,7 +1197,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
using ordinary FTP. */
|
||||
result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
|
||||
free(tmp);
|
||||
state(conn, SSH_SFTP_NEXT_QUOTE);
|
||||
if(result) {
|
||||
state(conn, SSH_SFTP_CLOSE);
|
||||
sshc->nextstate = SSH_NO_STATE;
|
||||
sshc->actualcode = result;
|
||||
}
|
||||
else
|
||||
state(conn, SSH_SFTP_NEXT_QUOTE);
|
||||
break;
|
||||
}
|
||||
else if(cmd) {
|
||||
@@ -1231,8 +1237,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
}
|
||||
|
||||
/*
|
||||
* SFTP is a binary protocol, so we don't send text commands to
|
||||
* the server. Instead, we scan for commands for commands used by
|
||||
* SFTP is a binary protocol, so we don't send text commands
|
||||
* to the server. Instead, we scan for commands used by
|
||||
* OpenSSH's sftp program and call the appropriate libssh2
|
||||
* functions.
|
||||
*/
|
||||
@@ -1672,7 +1678,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have restart point then we need to seek to the correct
|
||||
/* If we have a restart point then we need to seek to the correct
|
||||
position. */
|
||||
if(data->state.resume_from > 0) {
|
||||
/* Let's read off the proper amount of bytes from the input. */
|
||||
@@ -1807,8 +1813,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
|
||||
case SSH_SFTP_READDIR_INIT:
|
||||
Curl_pgrsSetDownloadSize(data, -1);
|
||||
if(data->set.opt_no_body)
|
||||
if(data->set.opt_no_body) {
|
||||
state(conn, SSH_STOP);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a directory that we are trying to get, so produce a directory
|
||||
@@ -2146,9 +2154,6 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
}
|
||||
}
|
||||
|
||||
if(data->set.opt_no_body)
|
||||
state(conn, SSH_SFTP_CLOSE);
|
||||
|
||||
/* Setup the actual download */
|
||||
if(data->req.size == 0) {
|
||||
/* no data to transfer */
|
||||
@@ -2170,6 +2175,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
conn->cselect_bits = CURL_CSELECT_IN;
|
||||
}
|
||||
if(result) {
|
||||
/* this should never occur; the close state should be entered
|
||||
at the time the error occurs */
|
||||
state(conn, SSH_SFTP_CLOSE);
|
||||
sshc->actualcode = result;
|
||||
}
|
||||
@@ -2197,7 +2204,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
|
||||
/* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
|
||||
After nextstate is executed,the control should come back to
|
||||
SSH_SFTP_CLOSE to pass the correct result back */
|
||||
if(sshc->nextstate != SSH_NO_STATE) {
|
||||
if(sshc->nextstate != SSH_NO_STATE &&
|
||||
sshc->nextstate != SSH_SFTP_CLOSE) {
|
||||
state(conn, sshc->nextstate);
|
||||
sshc->nextstate = SSH_SFTP_CLOSE;
|
||||
}
|
||||
@@ -3115,6 +3123,7 @@ static ssize_t sftp_send(struct connectdata *conn, int sockindex,
|
||||
|
||||
/*
|
||||
* Return number of received (decrypted) bytes
|
||||
* or <0 on error
|
||||
*/
|
||||
static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
|
||||
char *mem, size_t len, CURLcode *err)
|
||||
@@ -3129,6 +3138,10 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
|
||||
if(nread == LIBSSH2_ERROR_EAGAIN) {
|
||||
*err = CURLE_AGAIN;
|
||||
nread = -1;
|
||||
|
||||
}
|
||||
else if(nread < 0) {
|
||||
*err = libssh2_session_error_to_CURLE((int)nread);
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
|
||||
@@ -87,8 +87,6 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
#define CURL_TIMEOUT_EXPECT_100 1000 /* counting ms here */
|
||||
|
||||
/*
|
||||
* This function will call the read callback to fill our buffer with data
|
||||
* to upload.
|
||||
@@ -312,7 +310,20 @@ static int data_pending(const struct connectdata *conn)
|
||||
/* in the case of libssh2, we can never be really sure that we have emptied
|
||||
its internal buffers so we MUST always try until we get EAGAIN back */
|
||||
return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
|
||||
#if defined(USE_NGHTTP2)
|
||||
Curl_ssl_data_pending(conn, FIRSTSOCKET) ||
|
||||
/* For HTTP/2, we may read up everything including responde body
|
||||
with header fields in Curl_http_readwrite_headers. If no
|
||||
content-length is provided, curl waits for the connection
|
||||
close, which we emulate it using conn->proto.httpc.closed =
|
||||
TRUE. The thing is if we read everything, then http2_recv won't
|
||||
be called and we cannot signal the HTTP/2 stream has closed. As
|
||||
a workaround, we return nonzero here to call http2_recv. */
|
||||
((conn->handler->protocol&CURLPROTO_HTTP) && conn->httpversion == 20 &&
|
||||
conn->proto.httpc.closed);
|
||||
#else
|
||||
Curl_ssl_data_pending(conn, FIRSTSOCKET);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void read_rewind(struct connectdata *conn,
|
||||
@@ -600,7 +611,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
failf(data, "Failed writing data");
|
||||
return CURLE_WRITE_ERROR;
|
||||
}
|
||||
failf(data, "Problem (%d) in the Chunked-Encoded data", (int)res);
|
||||
failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
else if(CHUNKE_STOP == res) {
|
||||
@@ -839,7 +850,7 @@ static CURLcode readwrite_upload(struct SessionHandle *data,
|
||||
*didwhat &= ~KEEP_SEND; /* we didn't write anything actually */
|
||||
|
||||
/* set a timeout for the multi interface */
|
||||
Curl_expire(data, CURL_TIMEOUT_EXPECT_100);
|
||||
Curl_expire(data, data->set.expect_100_timeout);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1075,7 +1086,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
*/
|
||||
|
||||
long ms = Curl_tvdiff(k->now, k->start100);
|
||||
if(ms > CURL_TIMEOUT_EXPECT_100) {
|
||||
if(ms >= data->set.expect_100_timeout) {
|
||||
/* we've waited long enough, continue anyway */
|
||||
k->exp100 = EXP100_SEND_DATA;
|
||||
k->keepon |= KEEP_SEND;
|
||||
@@ -1969,7 +1980,7 @@ Curl_setup_transfer(
|
||||
|
||||
/* Set a timeout for the multi interface. Add the inaccuracy margin so
|
||||
that we don't fire slightly too early and get denied to run. */
|
||||
Curl_expire(data, CURL_TIMEOUT_EXPECT_100);
|
||||
Curl_expire(data, data->set.expect_100_timeout);
|
||||
}
|
||||
else {
|
||||
if(data->state.expect100header)
|
||||
|
||||
98
lib/url.c
98
lib/url.c
@@ -563,6 +563,10 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
|
||||
set->tcp_keepintvl = 60;
|
||||
set->tcp_keepidle = 60;
|
||||
|
||||
set->ssl_enable_npn = TRUE;
|
||||
set->ssl_enable_alpn = TRUE;
|
||||
|
||||
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1254,6 +1258,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
}
|
||||
break;
|
||||
|
||||
case CURLOPT_EXPECT_100_TIMEOUT_MS:
|
||||
/*
|
||||
* Time to wait for a response to a HTTP request containing an
|
||||
* Expect: 100-continue header before sending the data anyway.
|
||||
*/
|
||||
data->set.expect_100_timeout = va_arg(param, long);
|
||||
break;
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
case CURLOPT_CUSTOMREQUEST:
|
||||
@@ -2478,6 +2490,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
||||
case CURLOPT_TCP_KEEPINTVL:
|
||||
data->set.tcp_keepintvl = va_arg(param, long);
|
||||
break;
|
||||
case CURLOPT_SSL_ENABLE_NPN:
|
||||
data->set.ssl_enable_npn = (0 != va_arg(param, long))?TRUE:FALSE;
|
||||
break;
|
||||
case CURLOPT_SSL_ENABLE_ALPN:
|
||||
data->set.ssl_enable_alpn = (0 != va_arg(param, long))?TRUE:FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* unknown tag and its companion, just ignore: */
|
||||
@@ -2885,8 +2903,9 @@ ConnectionExists(struct SessionHandle *data,
|
||||
struct connectdata *check;
|
||||
struct connectdata *chosen = 0;
|
||||
bool canPipeline = IsPipeliningPossible(data, needle);
|
||||
bool wantNTLM = (data->state.authhost.want & CURLAUTH_NTLM) ||
|
||||
(data->state.authhost.want & CURLAUTH_NTLM_WB) ? TRUE : FALSE;
|
||||
bool wantNTLMhttp = ((data->state.authhost.want & CURLAUTH_NTLM) ||
|
||||
(data->state.authhost.want & CURLAUTH_NTLM_WB)) &&
|
||||
(needle->handler->protocol & CURLPROTO_HTTP) ? TRUE : FALSE;
|
||||
struct connectbundle *bundle;
|
||||
|
||||
*force_reuse = FALSE;
|
||||
@@ -3041,16 +3060,16 @@ ConnectionExists(struct SessionHandle *data,
|
||||
continue;
|
||||
}
|
||||
|
||||
if((needle->handler->protocol & CURLPROTO_FTP) ||
|
||||
((needle->handler->protocol & CURLPROTO_HTTP) && wantNTLM)) {
|
||||
/* This is FTP or HTTP+NTLM, verify that we're using the same name
|
||||
and password as well */
|
||||
if(!strequal(needle->user, check->user) ||
|
||||
!strequal(needle->passwd, check->passwd)) {
|
||||
/* one of them was different */
|
||||
continue;
|
||||
}
|
||||
credentialsMatch = TRUE;
|
||||
if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) ||
|
||||
wantNTLMhttp) {
|
||||
/* This protocol requires credentials per connection or is HTTP+NTLM,
|
||||
so verify that we're using the same name and password as well */
|
||||
if(!strequal(needle->user, check->user) ||
|
||||
!strequal(needle->passwd, check->passwd)) {
|
||||
/* one of them was different */
|
||||
continue;
|
||||
}
|
||||
credentialsMatch = TRUE;
|
||||
}
|
||||
|
||||
if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL ||
|
||||
@@ -3102,12 +3121,12 @@ ConnectionExists(struct SessionHandle *data,
|
||||
}
|
||||
|
||||
if(match) {
|
||||
/* If we are looking for an NTLM connection, check if this is already
|
||||
authenticating with the right credentials. If not, keep looking so
|
||||
that we can reuse NTLM connections if possible. (Especially we
|
||||
must not reuse the same connection if partway through
|
||||
a handshake!) */
|
||||
if(wantNTLM) {
|
||||
/* If we are looking for an HTTP+NTLM connection, check if this is
|
||||
already authenticating with the right credentials. If not, keep
|
||||
looking so that we can reuse NTLM connections if
|
||||
possible. (Especially we must not reuse the same connection if
|
||||
partway through a handshake!) */
|
||||
if(wantNTLMhttp) {
|
||||
if(credentialsMatch && check->ntlm.state != NTLMSTATE_NONE) {
|
||||
chosen = check;
|
||||
|
||||
@@ -3115,8 +3134,10 @@ ConnectionExists(struct SessionHandle *data,
|
||||
*force_reuse = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
else if(credentialsMatch)
|
||||
/* this is a backup choice */
|
||||
chosen = check;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(canPipeline) {
|
||||
@@ -3170,7 +3191,8 @@ ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
|
||||
{
|
||||
/* data->multi->maxconnects can be negative, deal with it. */
|
||||
size_t maxconnects =
|
||||
(data->multi->maxconnects < 0) ? 0 : data->multi->maxconnects;
|
||||
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
|
||||
data->multi->maxconnects;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
|
||||
/* Mark the current connection as 'unused' */
|
||||
@@ -3532,6 +3554,7 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
|
||||
conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
|
||||
conn->connection_id = -1; /* no ID */
|
||||
conn->port = -1; /* unknown at this point */
|
||||
conn->remote_port = -1; /* unknown */
|
||||
|
||||
/* Default protocol-independent behavior doesn't support persistent
|
||||
connections, so we set this to force-close. Protocols that support
|
||||
@@ -4054,7 +4077,7 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
|
||||
|
||||
/* only if remote_port was not already parsed off the URL we use the
|
||||
default port number */
|
||||
if(!conn->remote_port)
|
||||
if(conn->remote_port < 0)
|
||||
conn->remote_port = (unsigned short)conn->given->defport;
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -4748,24 +4771,21 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
|
||||
/* no CURLOPT_PORT given, extract the one from the URL */
|
||||
|
||||
char *rest;
|
||||
unsigned long port;
|
||||
long port;
|
||||
|
||||
port=strtoul(portptr+1, &rest, 10); /* Port number must be decimal */
|
||||
port=strtol(portptr+1, &rest, 10); /* Port number must be decimal */
|
||||
|
||||
if(rest != (portptr+1) && *rest == '\0') {
|
||||
/* The colon really did have only digits after it,
|
||||
* so it is either a port number or a mistake */
|
||||
|
||||
if(port > 0xffff) { /* Single unix standard says port numbers are
|
||||
* 16 bits long */
|
||||
failf(data, "Port number too large: %lu", port);
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
if((port < 0) || (port > 0xffff)) {
|
||||
/* Single unix standard says port numbers are 16 bits long */
|
||||
failf(data, "Port number out of range");
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
else if(rest != &portptr[1]) {
|
||||
*portptr = '\0'; /* cut off the name there */
|
||||
conn->remote_port = curlx_ultous(port);
|
||||
}
|
||||
else if(!port)
|
||||
else
|
||||
/* Browser behavior adaptation. If there's a colon with no digits after,
|
||||
just cut off the name there which makes us ignore the colon and just
|
||||
use the default port. Firefox and Chrome both do that. */
|
||||
@@ -4805,13 +4825,17 @@ static CURLcode override_login(struct SessionHandle *data,
|
||||
|
||||
conn->bits.netrc = FALSE;
|
||||
if(data->set.use_netrc != CURL_NETRC_IGNORED) {
|
||||
if(Curl_parsenetrc(conn->host.name,
|
||||
userp, passwdp,
|
||||
data->set.str[STRING_NETRC_FILE])) {
|
||||
int ret = Curl_parsenetrc(conn->host.name,
|
||||
userp, passwdp,
|
||||
data->set.str[STRING_NETRC_FILE]);
|
||||
if(ret > 0) {
|
||||
infof(data, "Couldn't find host %s in the "
|
||||
DOT_CHAR "netrc file; using defaults\n",
|
||||
conn->host.name);
|
||||
}
|
||||
else if(ret < 0 ) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
/* set bits.netrc TRUE to remember that we got the name from a .netrc
|
||||
file, so that it is safe to use even if we followed a Location: to a
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -296,18 +296,13 @@ struct ssl_connect_data {
|
||||
ssl_connect_state connecting_state;
|
||||
#endif /* USE_GNUTLS */
|
||||
#ifdef USE_POLARSSL
|
||||
#if POLARSSL_VERSION_NUMBER<0x01010000
|
||||
havege_state hs;
|
||||
#else
|
||||
/* from v1.1.0, use ctr_drbg and entropy */
|
||||
ctr_drbg_context ctr_drbg;
|
||||
entropy_context entropy;
|
||||
#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
|
||||
ssl_context ssl;
|
||||
ssl_session ssn;
|
||||
int server_fd;
|
||||
x509_cert cacert;
|
||||
x509_cert clicert;
|
||||
x509_crt cacert;
|
||||
x509_crt clicert;
|
||||
x509_crl crl;
|
||||
rsa_context rsa;
|
||||
ssl_connect_state connecting_state;
|
||||
@@ -388,7 +383,7 @@ struct curl_ssl_session {
|
||||
void *sessionid; /* as returned from the SSL layer */
|
||||
size_t idsize; /* if known, otherwise 0 */
|
||||
long age; /* just a number, the higher the more recent */
|
||||
unsigned short remote_port; /* remote port to connect to */
|
||||
int remote_port; /* remote port to connect to */
|
||||
struct ssl_config_data ssl_config; /* setup for this session */
|
||||
};
|
||||
|
||||
@@ -435,6 +430,8 @@ struct ntlmdata {
|
||||
#else
|
||||
unsigned int flags;
|
||||
unsigned char nonce[8];
|
||||
void* target_info; /* TargetInfo received in the ntlm type-2 message */
|
||||
unsigned int target_info_len;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -580,7 +577,6 @@ struct Curl_async {
|
||||
typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *);
|
||||
typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool);
|
||||
|
||||
|
||||
enum expect100 {
|
||||
EXP100_SEND_DATA, /* enough waiting, just send the body now */
|
||||
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
|
||||
@@ -589,6 +585,19 @@ enum expect100 {
|
||||
EXP100_FAILED /* used on 417 Expectation Failed */
|
||||
};
|
||||
|
||||
enum upgrade101 {
|
||||
UPGR101_INIT, /* default state */
|
||||
UPGR101_REQUESTED, /* upgrade requested */
|
||||
UPGR101_RECEIVED, /* response received */
|
||||
UPGR101_WORKING /* talking upgraded protocol */
|
||||
};
|
||||
|
||||
enum negotiatenpn {
|
||||
NPN_INIT, /* default state */
|
||||
NPN_HTTP1_1, /* HTTP/1.1 negotiated */
|
||||
NPN_HTTP2_DRAFT09 /* HTTP-draft-0.9/2.0 negotiated */
|
||||
};
|
||||
|
||||
/*
|
||||
* Request specific data in the easy handle (SessionHandle). Previously,
|
||||
* these members were on the connectdata struct but since a conn struct may
|
||||
@@ -639,6 +648,7 @@ struct SingleRequest {
|
||||
'RTSP/1.? XXX' line */
|
||||
struct timeval start100; /* time stamp to wait for the 100 code from */
|
||||
enum expect100 exp100; /* expect 100 continue state */
|
||||
enum upgrade101 upgr101; /* 101 upgrade state */
|
||||
|
||||
int auto_decoding; /* What content encoding. sec 3.5, RFC2616. */
|
||||
|
||||
@@ -785,6 +795,8 @@ struct Curl_handler {
|
||||
gets a default */
|
||||
#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle
|
||||
url query strings (?foo=bar) ! */
|
||||
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login creditials per request
|
||||
as opposed to per connection */
|
||||
|
||||
|
||||
/* return the count of bytes sent, or -1 on error */
|
||||
@@ -853,8 +865,7 @@ struct connectdata {
|
||||
struct hostname proxy;
|
||||
|
||||
long port; /* which port to use locally */
|
||||
unsigned short remote_port; /* what remote port to connect to,
|
||||
not the proxy port! */
|
||||
int remote_port; /* what remote port to connect to, not the proxy port! */
|
||||
|
||||
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
|
||||
ip address and port number whenever an outgoing connection is
|
||||
@@ -1039,6 +1050,8 @@ struct connectdata {
|
||||
TUNNEL_COMPLETE /* CONNECT response received completely */
|
||||
} tunnel_state[2]; /* two separate ones to allow FTP */
|
||||
struct connectbundle *bundle; /* The bundle we are member of */
|
||||
|
||||
enum negotiatenpn negnpn;
|
||||
};
|
||||
|
||||
/* The end of connectdata. */
|
||||
@@ -1576,6 +1589,11 @@ struct UserDefined {
|
||||
long tcp_keepintvl; /* seconds between TCP keepalive probes */
|
||||
|
||||
size_t maxconnects; /* Max idle connections in the connection cache */
|
||||
|
||||
bool ssl_enable_npn; /* TLS NPN extension? */
|
||||
bool ssl_enable_alpn; /* TLS ALPN extension? */
|
||||
|
||||
long expect_100_timeout; /* in milliseconds */
|
||||
};
|
||||
|
||||
struct Names {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
|
||||
* Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2010 - 2014, 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
|
||||
@@ -390,7 +390,7 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||
/*
|
||||
* Use axTLS's non-blocking connection feature to open an SSL connection.
|
||||
* This is called after a TCP connection is already established.
|
||||
*/
|
||||
*/
|
||||
CURLcode Curl_axtls_connect_nonblocking(
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
@@ -398,6 +398,7 @@ CURLcode Curl_axtls_connect_nonblocking(
|
||||
{
|
||||
CURLcode conn_step;
|
||||
int ssl_fcn_return;
|
||||
int i;
|
||||
|
||||
*done = FALSE;
|
||||
/* connectdata is calloc'd and connecting_state is only changed in this
|
||||
@@ -414,14 +415,17 @@ CURLcode Curl_axtls_connect_nonblocking(
|
||||
if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
|
||||
/* Check to make sure handshake was ok. */
|
||||
if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
|
||||
ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
|
||||
if(ssl_fcn_return < 0) {
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
|
||||
return map_error_to_curl(ssl_fcn_return);
|
||||
}
|
||||
else {
|
||||
return CURLE_OK; /* Return control to caller for retries */
|
||||
/* Loop to perform more work in between sleeps. This is work around the
|
||||
fact that axtls does not expose any knowledge about when work needs
|
||||
to be performed. This can save ~25% of time on SSL handshakes. */
|
||||
for(i=0; i<5; i++) {
|
||||
ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
|
||||
if(ssl_fcn_return < 0) {
|
||||
Curl_axtls_close(conn, sockindex);
|
||||
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
|
||||
return map_error_to_curl(ssl_fcn_return);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
infof (conn->data, "handshake completed successfully\n");
|
||||
|
||||
@@ -1323,20 +1323,26 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
|
||||
|
||||
/* If this is a domain name and not an IP address, then configure SNI.
|
||||
/* Configure hostname check. SNI is used if available.
|
||||
* Both hostname check and SNI require SSLSetPeerDomainName().
|
||||
* Also: the verifyhost setting influences SNI usage */
|
||||
/* If this is a domain name and not an IP address, then configure SNI: */
|
||||
if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
|
||||
#ifdef ENABLE_IPV6
|
||||
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
|
||||
#endif
|
||||
data->set.ssl.verifyhost) {
|
||||
if(data->set.ssl.verifyhost) {
|
||||
err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
|
||||
strlen(conn->host.name));
|
||||
strlen(conn->host.name));
|
||||
|
||||
if(err != noErr) {
|
||||
infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
|
||||
#ifdef ENABLE_IPV6
|
||||
|| (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
|
||||
#endif
|
||||
) {
|
||||
infof(data, "WARNING: using IP address, SNI is being disabled by "
|
||||
"the OS.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable cipher suites that ST supports but are not safe. These ciphers
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012 - 2013, Marc Hoersken, <info@marc-hoersken.de>
|
||||
* Copyright (C) 2012 - 2014, Marc Hoersken, <info@marc-hoersken.de>
|
||||
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
|
||||
* Copyright (C) 2012 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2014, 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
|
||||
@@ -156,17 +156,6 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
infof(data, "schannel: disable server certificate revocation checks\n");
|
||||
}
|
||||
|
||||
if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
|
||||
#ifdef ENABLE_IPV6
|
||||
|| Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
|
||||
#endif
|
||||
) {
|
||||
schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
|
||||
infof(data, "schannel: using IP address, SNI is being disabled by "
|
||||
"disabling the servername check against the "
|
||||
"subject names in server certificates.\n");
|
||||
}
|
||||
|
||||
if(!data->set.ssl.verifyhost) {
|
||||
schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
|
||||
infof(data, "schannel: verifyhost setting prevents Schannel from "
|
||||
@@ -195,6 +184,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
case CURL_SSLVERSION_SSLv2:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
|
||||
break;
|
||||
default:
|
||||
schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
|
||||
SP_PROT_TLS1_1_CLIENT |
|
||||
SP_PROT_TLS1_2_CLIENT |
|
||||
SP_PROT_SSL3_CLIENT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate memory for the re-usable credential handle */
|
||||
@@ -222,6 +217,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
|
||||
}
|
||||
}
|
||||
|
||||
/* Warn if SNI is disabled due to use of an IP address */
|
||||
if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
|
||||
#ifdef ENABLE_IPV6
|
||||
|| Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
|
||||
#endif
|
||||
) {
|
||||
infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
|
||||
}
|
||||
|
||||
/* setup output buffer */
|
||||
InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
|
||||
InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
|
||||
|
||||
@@ -89,6 +89,15 @@ static bool gtls_inited = FALSE;
|
||||
# if (GNUTLS_VERSION_NUMBER >= 0x020c03)
|
||||
# define GNUTLS_MAPS_WINSOCK_ERRORS 1
|
||||
# endif
|
||||
|
||||
# ifdef USE_NGHTTP2
|
||||
# undef HAS_ALPN
|
||||
# if (GNUTLS_VERSION_NUMBER >= 0x030200)
|
||||
# define HAS_ALPN
|
||||
# else
|
||||
# error http2 builds require GnuTLS >= 3.2.0 for ALPN support
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -374,6 +383,10 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
const char* prioritylist;
|
||||
const char *err;
|
||||
#endif
|
||||
#ifdef HAS_ALPN
|
||||
int protocols_size = 2;
|
||||
gnutls_datum_t protocols[2];
|
||||
#endif
|
||||
|
||||
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
||||
/* to make us tolerant against being called more than once for the
|
||||
@@ -556,6 +569,22 @@ gtls_connect_step1(struct connectdata *conn,
|
||||
rc = gnutls_priority_set_direct(session, prioritylist, &err);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
|
||||
if(data->set.ssl_enable_alpn) {
|
||||
protocols[0].data = NGHTTP2_PROTO_VERSION_ID;
|
||||
protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
protocols[1].data = ALPN_HTTP_1_1;
|
||||
protocols[1].size = ALPN_HTTP_1_1_LENGTH;
|
||||
gnutls_alpn_set_protocols(session, protocols, protocols_size, 0);
|
||||
infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
|
||||
ALPN_HTTP_1_1);
|
||||
}
|
||||
else {
|
||||
infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(rc != GNUTLS_E_SUCCESS) {
|
||||
failf(data, "Did you pass a valid GnuTLS cipher list?");
|
||||
@@ -637,6 +666,9 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
int rc;
|
||||
int incache;
|
||||
void *ssl_sessionid;
|
||||
#ifdef HAS_ALPN
|
||||
gnutls_datum_t proto;
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* This function will return the peer's raw certificate (chain) as sent by
|
||||
@@ -841,6 +873,29 @@ gtls_connect_step3(struct connectdata *conn,
|
||||
ptr = gnutls_mac_get_name(gnutls_mac_get(session));
|
||||
infof(data, "\t MAC: %s\n", ptr);
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
if(data->set.ssl_enable_alpn) {
|
||||
rc = gnutls_alpn_get_selected_protocol(session, &proto);
|
||||
if(rc == 0) {
|
||||
infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
|
||||
proto.data);
|
||||
|
||||
if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
|
||||
conn->negnpn = NPN_HTTP2_DRAFT09;
|
||||
}
|
||||
else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
|
||||
proto.data, ALPN_HTTP_1_1_LENGTH) == 0) {
|
||||
conn->negnpn = NPN_HTTP1_1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
infof(data, "ALPN, server did not agree to a protocol\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
conn->ssl[sockindex].state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = gtls_recv;
|
||||
conn->send[sockindex] = gtls_send;
|
||||
|
||||
154
lib/vtls/nss.c
154
lib/vtls/nss.c
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -123,9 +123,12 @@ static const cipher_s cipherlist[] = {
|
||||
{"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
|
||||
{"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
|
||||
/* AES ciphers. */
|
||||
{"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
|
||||
{"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
|
||||
{"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
|
||||
{"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
|
||||
{"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
|
||||
{"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
|
||||
#ifdef NSS_ENABLE_ECC
|
||||
/* ECC ciphers. */
|
||||
{"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA},
|
||||
{"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
|
||||
@@ -152,19 +155,26 @@ static const cipher_s cipherlist[] = {
|
||||
{"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
|
||||
{"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
|
||||
{"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
|
||||
#ifdef TLS_RSA_WITH_NULL_SHA256
|
||||
/* new HMAC-SHA256 cipher suites specified in RFC */
|
||||
{"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256},
|
||||
{"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256},
|
||||
{"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256},
|
||||
{"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
|
||||
{"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
|
||||
{"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
|
||||
{"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
|
||||
#endif
|
||||
#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
|
||||
/* AES GCM cipher suites in RFC 5288 and RFC 5289 */
|
||||
{"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256},
|
||||
{"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
|
||||
{"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
|
||||
{"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
{"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
{"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
|
||||
{"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
|
||||
#endif
|
||||
};
|
||||
|
||||
/* following ciphers are new in NSS 3.4 and not enabled by default, therefore
|
||||
they are enabled explicitly */
|
||||
static const int enable_ciphers_by_default[] = {
|
||||
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
SSL_NULL_WITH_NULL_NULL
|
||||
};
|
||||
|
||||
static const char* pem_library = "libnsspem.so";
|
||||
@@ -191,14 +201,13 @@ static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
|
||||
PRBool cipher_state[NUM_OF_CIPHERS];
|
||||
PRBool found;
|
||||
char *cipher;
|
||||
SECStatus rv;
|
||||
|
||||
/* First disable all ciphers. This uses a different max value in case
|
||||
* NSS adds more ciphers later we don't want them available by
|
||||
* accident
|
||||
*/
|
||||
for(i=0; i<SSL_NumImplementedCiphers; i++) {
|
||||
SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
|
||||
SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], PR_FALSE);
|
||||
}
|
||||
|
||||
/* Set every entry in our list to false */
|
||||
@@ -238,8 +247,10 @@ static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
|
||||
|
||||
/* Finally actually enable the selected ciphers */
|
||||
for(i=0; i<NUM_OF_CIPHERS; i++) {
|
||||
rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
|
||||
if(rv != SECSuccess) {
|
||||
if(!cipher_state[i])
|
||||
continue;
|
||||
|
||||
if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) {
|
||||
failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
|
||||
return SECFailure;
|
||||
}
|
||||
@@ -615,8 +626,48 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
|
||||
*/
|
||||
static void HandshakeCallback(PRFileDesc *sock, void *arg)
|
||||
{
|
||||
#ifdef USE_NGHTTP2
|
||||
struct connectdata *conn = (struct connectdata*) arg;
|
||||
unsigned int buflenmax = 50;
|
||||
unsigned char buf[50];
|
||||
unsigned int buflen;
|
||||
SSLNextProtoState state;
|
||||
|
||||
if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
|
||||
|
||||
switch(state) {
|
||||
case SSL_NEXT_PROTO_NO_SUPPORT:
|
||||
case SSL_NEXT_PROTO_NO_OVERLAP:
|
||||
infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n");
|
||||
return;
|
||||
#ifdef SSL_ENABLE_ALPN
|
||||
case SSL_NEXT_PROTO_SELECTED:
|
||||
infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
|
||||
break;
|
||||
#endif
|
||||
case SSL_NEXT_PROTO_NEGOTIATED:
|
||||
infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)
|
||||
== 0) {
|
||||
conn->negnpn = NPN_HTTP2_DRAFT09;
|
||||
}
|
||||
else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf,
|
||||
ALPN_HTTP_1_1_LENGTH)) {
|
||||
conn->negnpn = NPN_HTTP1_1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)sock;
|
||||
(void)arg;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void display_cert_info(struct SessionHandle *data,
|
||||
@@ -1194,8 +1245,9 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
|
||||
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;
|
||||
}
|
||||
return CURLE_OK;
|
||||
/* intentional fall-through to default to highest TLS version if possible */
|
||||
|
||||
case CURL_SSLVERSION_TLSv1:
|
||||
sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
|
||||
@@ -1254,7 +1306,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
CURLcode curlerr;
|
||||
const int *cipher_to_enable;
|
||||
PRSocketOptionData sock_opt;
|
||||
long time_left;
|
||||
PRUint32 timeout;
|
||||
@@ -1264,6 +1315,17 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
SSL_LIBRARY_VERSION_TLS_1_0 /* max */
|
||||
};
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
|
||||
unsigned int alpn_protos_len = NGHTTP2_PROTO_VERSION_ID_LEN +
|
||||
ALPN_HTTP_1_1_LENGTH + 2;
|
||||
unsigned char alpn_protos[NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH
|
||||
+ 2];
|
||||
int cur = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
if(connssl->state == ssl_connection_complete)
|
||||
return CURLE_OK;
|
||||
|
||||
@@ -1345,16 +1407,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
/* reset the flag to avoid an infinite loop */
|
||||
data->state.ssl_connect_retry = FALSE;
|
||||
|
||||
/* enable all ciphers from enable_ciphers_by_default */
|
||||
cipher_to_enable = enable_ciphers_by_default;
|
||||
while(SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) {
|
||||
if(SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) {
|
||||
curlerr = CURLE_SSL_CIPHER;
|
||||
goto error;
|
||||
}
|
||||
cipher_to_enable++;
|
||||
}
|
||||
|
||||
if(data->set.ssl.cipher_list) {
|
||||
if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
|
||||
curlerr = CURLE_SSL_CIPHER;
|
||||
@@ -1374,7 +1426,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
if(SSL_HandshakeCallback(model, HandshakeCallback, NULL) != SECSuccess)
|
||||
if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
|
||||
goto error;
|
||||
|
||||
if(data->set.ssl.verifypeer) {
|
||||
@@ -1437,6 +1489,46 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
|
||||
SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
|
||||
}
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
|
||||
#ifdef SSL_ENABLE_NPN
|
||||
if(data->set.ssl_enable_npn) {
|
||||
if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess)
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SSL_ENABLE_ALPN
|
||||
if(data->set.ssl_enable_alpn) {
|
||||
if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE)
|
||||
!= SECSuccess)
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
|
||||
if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) {
|
||||
alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
cur++;
|
||||
memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
cur += NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH;
|
||||
cur++;
|
||||
memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
|
||||
|
||||
if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len)
|
||||
!= SECSuccess)
|
||||
goto error;
|
||||
}
|
||||
else {
|
||||
infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Force handshake on next I/O */
|
||||
SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
|
||||
|
||||
|
||||
@@ -1399,6 +1399,76 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
|
||||
# define use_sni(x) Curl_nop_stmt
|
||||
#endif
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
|
||||
#undef HAS_ALPN
|
||||
#if defined(HAVE_SSL_CTX_SET_ALPN_PROTOS) && \
|
||||
defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
|
||||
# define HAS_ALPN 1
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || \
|
||||
defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
# if !defined(HAS_ALPN)
|
||||
# error http2 builds require OpenSSL with NPN or ALPN support
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* in is a list of lenght prefixed strings. this function has to select
|
||||
* the protocol we want to use from the list and write its string into out.
|
||||
*/
|
||||
static int
|
||||
select_next_proto_cb(SSL *ssl,
|
||||
unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen,
|
||||
void *arg)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata*) arg;
|
||||
int retval = nghttp2_select_next_protocol(out, outlen, in, inlen);
|
||||
(void)ssl;
|
||||
|
||||
if(retval == 1) {
|
||||
infof(conn->data, "NPN, negotiated HTTP2\n");
|
||||
conn->negnpn = NPN_HTTP2_DRAFT09;
|
||||
}
|
||||
else if(retval == 0) {
|
||||
infof(conn->data, "NPN, negotiated HTTP1.1\n");
|
||||
conn->negnpn = NPN_HTTP1_1;
|
||||
}
|
||||
else {
|
||||
infof(conn->data, "NPN, no overlap, negotiated nothing\n");
|
||||
}
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *
|
||||
get_ssl_version_txt(SSL_SESSION *session)
|
||||
{
|
||||
if(NULL == session)
|
||||
return "";
|
||||
|
||||
switch(session->ssl_version) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
|
||||
case TLS1_2_VERSION:
|
||||
return "TLSv1.2";
|
||||
case TLS1_1_VERSION:
|
||||
return "TLSv1.1";
|
||||
#endif
|
||||
case TLS1_VERSION:
|
||||
return "TLSv1.0";
|
||||
case SSL3_VERSION:
|
||||
return "SSLv3";
|
||||
case SSL2_VERSION:
|
||||
return "SSLv2";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
static CURLcode
|
||||
ossl_connect_step1(struct connectdata *conn,
|
||||
int sockindex)
|
||||
@@ -1419,6 +1489,9 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
#else
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAS_ALPN
|
||||
unsigned char protocols[128];
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||
@@ -1617,6 +1690,36 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
|
||||
SSL_CTX_set_options(connssl->ctx, ctx_options);
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
|
||||
if(data->set.ssl_enable_npn) {
|
||||
SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb,
|
||||
conn);
|
||||
}
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
if(data->set.ssl_enable_alpn) {
|
||||
protocols[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
memcpy(&protocols[1], NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
|
||||
protocols[NGHTTP2_PROTO_VERSION_ID_LEN+1] = ALPN_HTTP_1_1_LENGTH;
|
||||
memcpy(&protocols[NGHTTP2_PROTO_VERSION_ID_LEN+2], ALPN_HTTP_1_1,
|
||||
ALPN_HTTP_1_1_LENGTH);
|
||||
|
||||
/* expects length prefixed preference ordered list of protocols in wire
|
||||
* format
|
||||
*/
|
||||
SSL_CTX_set_alpn_protos(connssl->ctx, protocols,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH + 2);
|
||||
|
||||
infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
|
||||
ALPN_HTTP_1_1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
|
||||
if(!cert_stuff(conn,
|
||||
connssl->ctx,
|
||||
@@ -1788,6 +1891,10 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
struct SessionHandle *data = conn->data;
|
||||
int err;
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
#ifdef HAS_ALPN
|
||||
char* neg_protocol;
|
||||
int len = 0;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
||||
|| ssl_connect_2_reading == connssl->connecting_state
|
||||
@@ -1881,9 +1988,34 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
connssl->connecting_state = ssl_connect_3;
|
||||
|
||||
/* Informational message */
|
||||
infof (data, "SSL connection using %s\n",
|
||||
infof (data, "SSL connection using %s / %s\n",
|
||||
get_ssl_version_txt(SSL_get_session(connssl->handle)),
|
||||
SSL_get_cipher(connssl->handle));
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
|
||||
* negotiated
|
||||
*/
|
||||
if(data->set.ssl_enable_alpn) {
|
||||
SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
|
||||
if(len != 0) {
|
||||
infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
|
||||
|
||||
if(len == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len) == 0) {
|
||||
conn->negnpn = NPN_HTTP2_DRAFT09;
|
||||
}
|
||||
else if(len == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
|
||||
neg_protocol, ALPN_HTTP_1_1_LENGTH) == 0) {
|
||||
conn->negnpn = NPN_HTTP1_1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
infof(data, "ALPN, server did not agree to a protocol\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
|
||||
* Copyright (C) 2012 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2014, 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
|
||||
@@ -37,25 +37,13 @@
|
||||
#include <polarssl/x509.h>
|
||||
#include <polarssl/version.h>
|
||||
|
||||
#if POLARSSL_VERSION_NUMBER >= 0x01000000
|
||||
#include <polarssl/error.h>
|
||||
#endif /* POLARSSL_VERSION_NUMBER >= 0x01000000 */
|
||||
#if POLARSSL_VERSION_NUMBER < 0x01030000
|
||||
#error too old PolarSSL
|
||||
#endif
|
||||
|
||||
#if POLARSSL_VERSION_NUMBER>0x01010000
|
||||
#include <polarssl/error.h>
|
||||
#include <polarssl/entropy.h>
|
||||
#include <polarssl/ctr_drbg.h>
|
||||
#else
|
||||
#include <polarssl/havege.h>
|
||||
#endif /* POLARSSL_VERSION_NUMBER>0x01010000 */
|
||||
|
||||
|
||||
#if POLARSSL_VERSION_NUMBER<0x01000000
|
||||
/*
|
||||
Earlier versions of polarssl had no WANT_READ or WANT_WRITE, only TRY_AGAIN
|
||||
*/
|
||||
#define POLARSSL_ERR_NET_WANT_READ POLARSSL_ERR_NET_TRY_AGAIN
|
||||
#define POLARSSL_ERR_NET_WANT_WRITE POLARSSL_ERR_NET_TRY_AGAIN
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
@@ -79,7 +67,7 @@
|
||||
#define THREADING_SUPPORT
|
||||
#endif
|
||||
|
||||
#if defined(THREADING_SUPPORT) && POLARSSL_VERSION_NUMBER>0x01010000
|
||||
#if defined(THREADING_SUPPORT)
|
||||
static entropy_context entropy;
|
||||
|
||||
static int entropy_init_initialized = 0;
|
||||
@@ -110,13 +98,13 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
|
||||
}
|
||||
/* end of entropy_func_mutex() */
|
||||
|
||||
#endif /* THREADING_SUPPORT && POLARSSL_VERSION_NUMBER>0x01010000 */
|
||||
#endif /* THREADING_SUPPORT */
|
||||
|
||||
/* Define this to enable lots of debugging for PolarSSL */
|
||||
#undef POLARSSL_DEBUG
|
||||
|
||||
#ifdef POLARSSL_DEBUG
|
||||
static void polarssl_debug(void *context, int level, char *line)
|
||||
static void polarssl_debug(void *context, int level, const char *line)
|
||||
{
|
||||
struct SessionHandle *data = NULL;
|
||||
|
||||
@@ -125,7 +113,8 @@ static void polarssl_debug(void *context, int level, char *line)
|
||||
|
||||
data = (struct SessionHandle *)context;
|
||||
|
||||
infof(data, "%s\n", line);
|
||||
infof(data, "%s", line);
|
||||
(void) level;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
@@ -163,9 +152,6 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
|
||||
sni = FALSE; /* SSLv3 has no SNI */
|
||||
|
||||
#if POLARSSL_VERSION_NUMBER<0x01010000
|
||||
havege_init(&connssl->hs);
|
||||
#else
|
||||
#ifdef THREADING_SUPPORT
|
||||
entropy_init_mutex(&entropy);
|
||||
|
||||
@@ -189,14 +175,13 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
-ret, errorbuf);
|
||||
}
|
||||
#endif /* THREADING_SUPPORT */
|
||||
#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
|
||||
|
||||
/* Load the trusted CA */
|
||||
memset(&connssl->cacert, 0, sizeof(x509_cert));
|
||||
memset(&connssl->cacert, 0, sizeof(x509_crt));
|
||||
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
ret = x509parse_crtfile(&connssl->cacert,
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
ret = x509_crt_parse_file(&connssl->cacert,
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
|
||||
if(ret<0) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
@@ -211,11 +196,11 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
}
|
||||
|
||||
/* Load the client certificate */
|
||||
memset(&connssl->clicert, 0, sizeof(x509_cert));
|
||||
memset(&connssl->clicert, 0, sizeof(x509_crt));
|
||||
|
||||
if(data->set.str[STRING_CERT]) {
|
||||
ret = x509parse_crtfile(&connssl->clicert,
|
||||
data->set.str[STRING_CERT]);
|
||||
ret = x509_crt_parse_file(&connssl->clicert,
|
||||
data->set.str[STRING_CERT]);
|
||||
|
||||
if(ret) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
@@ -230,9 +215,17 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
|
||||
/* Load the client private key */
|
||||
if(data->set.str[STRING_KEY]) {
|
||||
ret = x509parse_keyfile(&connssl->rsa,
|
||||
data->set.str[STRING_KEY],
|
||||
data->set.str[STRING_KEY_PASSWD]);
|
||||
pk_context pk;
|
||||
pk_init(&pk);
|
||||
ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
|
||||
data->set.str[STRING_KEY_PASSWD]);
|
||||
if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
|
||||
ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
|
||||
if(ret == 0)
|
||||
rsa_copy(&connssl->rsa, pk_rsa(pk));
|
||||
else
|
||||
rsa_free(&connssl->rsa);
|
||||
pk_free(&pk);
|
||||
|
||||
if(ret) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
@@ -249,8 +242,8 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
memset(&connssl->crl, 0, sizeof(x509_crl));
|
||||
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
ret = x509parse_crlfile(&connssl->crl,
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
ret = x509_crl_parse_file(&connssl->crl,
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
|
||||
if(ret) {
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
@@ -274,45 +267,28 @@ polarssl_connect_step1(struct connectdata *conn,
|
||||
ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
|
||||
ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
|
||||
|
||||
#if POLARSSL_VERSION_NUMBER<0x01010000
|
||||
ssl_set_rng(&connssl->ssl, havege_rand,
|
||||
&connssl->hs);
|
||||
#else
|
||||
ssl_set_rng(&connssl->ssl, ctr_drbg_random,
|
||||
&connssl->ctr_drbg);
|
||||
#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
|
||||
ssl_set_bio(&connssl->ssl,
|
||||
net_recv, &conn->sock[sockindex],
|
||||
net_send, &conn->sock[sockindex]);
|
||||
|
||||
|
||||
#if POLARSSL_VERSION_NUMBER<0x01000000
|
||||
ssl_set_ciphers(&connssl->ssl, ssl_default_ciphers);
|
||||
#else
|
||||
ssl_set_ciphersuites(&connssl->ssl, ssl_default_ciphersuites);
|
||||
#endif
|
||||
ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
|
||||
if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
|
||||
memcpy(&connssl->ssn, old_session, old_session_size);
|
||||
infof(data, "PolarSSL re-using session\n");
|
||||
}
|
||||
|
||||
/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's
|
||||
1.1.4 version and the like */
|
||||
#if POLARSSL_VERSION_NUMBER<0x01020000
|
||||
ssl_set_session(&connssl->ssl, 1, 600,
|
||||
&connssl->ssn);
|
||||
#else
|
||||
ssl_set_session(&connssl->ssl,
|
||||
&connssl->ssn);
|
||||
#endif
|
||||
|
||||
ssl_set_ca_chain(&connssl->ssl,
|
||||
&connssl->cacert,
|
||||
&connssl->crl,
|
||||
conn->host.name);
|
||||
|
||||
ssl_set_own_cert(&connssl->ssl,
|
||||
&connssl->clicert, &connssl->rsa);
|
||||
ssl_set_own_cert_rsa(&connssl->ssl,
|
||||
&connssl->clicert, &connssl->rsa);
|
||||
|
||||
if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
|
||||
#ifdef ENABLE_IPV6
|
||||
@@ -376,13 +352,7 @@ polarssl_connect_step2(struct connectdata *conn,
|
||||
}
|
||||
|
||||
infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
|
||||
#if POLARSSL_VERSION_NUMBER<0x01000000
|
||||
ssl_get_cipher(&conn->ssl[sockindex].ssl)
|
||||
#elif POLARSSL_VERSION_NUMBER >= 0x01010000
|
||||
ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
|
||||
#else
|
||||
ssl_get_ciphersuite_name(&conn->ssl[sockindex].ssl)
|
||||
#endif
|
||||
);
|
||||
|
||||
ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
|
||||
@@ -405,25 +375,12 @@ polarssl_connect_step2(struct connectdata *conn,
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
|
||||
/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's
|
||||
1.1.4 version and the like */
|
||||
#if POLARSSL_VERSION_NUMBER<0x01020000
|
||||
if(conn->ssl[sockindex].ssl.peer_cert) {
|
||||
#else
|
||||
if(ssl_get_peer_cert(&(connssl->ssl))) {
|
||||
#endif
|
||||
/* If the session was resumed, there will be no peer certs */
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
/* PolarSSL SVN revision r1316 to r1317, matching <1.2.0 is to cover Ubuntu's
|
||||
1.1.4 version and the like */
|
||||
#if POLARSSL_VERSION_NUMBER<0x01020000
|
||||
if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
|
||||
conn->ssl[sockindex].ssl.peer_cert) != -1)
|
||||
#else
|
||||
if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
|
||||
ssl_get_peer_cert(&(connssl->ssl))) != -1)
|
||||
#endif
|
||||
if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
|
||||
ssl_get_peer_cert(&(connssl->ssl))) != -1)
|
||||
infof(data, "Dumping cert info:\n%s\n", buffer);
|
||||
}
|
||||
|
||||
@@ -508,8 +465,8 @@ void Curl_polarssl_close_all(struct SessionHandle *data)
|
||||
void Curl_polarssl_close(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
rsa_free(&conn->ssl[sockindex].rsa);
|
||||
x509_free(&conn->ssl[sockindex].clicert);
|
||||
x509_free(&conn->ssl[sockindex].cacert);
|
||||
x509_crt_free(&conn->ssl[sockindex].clicert);
|
||||
x509_crt_free(&conn->ssl[sockindex].cacert);
|
||||
x509_crl_free(&conn->ssl[sockindex].crl);
|
||||
ssl_free(&conn->ssl[sockindex].ssl);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#define MD5_DIGEST_LENGTH 16 /* fixed size */
|
||||
#endif
|
||||
|
||||
/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
|
||||
#define ALPN_HTTP_1_1_LENGTH 8
|
||||
#define ALPN_HTTP_1_1 "http/1.0"
|
||||
|
||||
bool Curl_ssl_config_matches(struct ssl_config_data* data,
|
||||
struct ssl_config_data* needle);
|
||||
bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -400,6 +400,20 @@ curl_socket_t curlx_sitosk(int i)
|
||||
|
||||
#endif /* USE_WINSOCK */
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
|
||||
ssize_t curlx_read(int fd, void *buf, size_t count)
|
||||
{
|
||||
return (ssize_t)read(fd, buf, curlx_uztoui(count));
|
||||
}
|
||||
|
||||
ssize_t curlx_write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
return (ssize_t)write(fd, buf, curlx_uztoui(count));
|
||||
}
|
||||
|
||||
#endif /* WIN32 || _WIN32 */
|
||||
|
||||
#if defined(__INTEL_COMPILER) && defined(__unix__)
|
||||
|
||||
int curlx_FD_ISSET(int fd, fd_set *fdset)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -60,6 +60,21 @@ curl_socket_t curlx_sitosk(int i);
|
||||
|
||||
#endif /* USE_WINSOCK */
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
|
||||
ssize_t curlx_read(int fd, void *buf, size_t count);
|
||||
|
||||
ssize_t curlx_write(int fd, const void *buf, size_t count);
|
||||
|
||||
#ifndef BUILDING_WARNLESS_C
|
||||
# undef read
|
||||
# define read(fd, buf, count) curlx_read(fd, buf, count)
|
||||
# undef write
|
||||
# define write(fd, buf, count) curlx_write(fd, buf, count)
|
||||
#endif
|
||||
|
||||
#endif /* WIN32 || _WIN32 */
|
||||
|
||||
#if defined(__INTEL_COMPILER) && defined(__unix__)
|
||||
|
||||
int curlx_FD_ISSET(int fd, fd_set *fdset);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -666,31 +666,6 @@ const char * Curl_DNtostr(curl_asn1Element * dn)
|
||||
return (const char *) buf;
|
||||
}
|
||||
|
||||
static const char * checkOID(const char * beg, const char * end,
|
||||
const char * oid)
|
||||
{
|
||||
curl_asn1Element e;
|
||||
const char * ccp;
|
||||
const char * p;
|
||||
bool matched;
|
||||
|
||||
/* Check if first ASN.1 element at `beg' is the given OID.
|
||||
Return a pointer in the source after the OID if found, else NULL. */
|
||||
|
||||
ccp = Curl_getASN1Element(&e, beg, end);
|
||||
if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
|
||||
return (const char *) NULL;
|
||||
|
||||
p = OID2str(e.beg, e.end, FALSE);
|
||||
if(!p)
|
||||
return (const char *) NULL;
|
||||
|
||||
matched = !strcmp(p, oid);
|
||||
free((char *) p);
|
||||
return matched? ccp: (const char *) NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* X509 parser.
|
||||
*/
|
||||
@@ -1044,6 +1019,33 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
|
||||
|
||||
#if defined(USE_QSOSSL) || defined(USE_GSKIT)
|
||||
|
||||
static const char * checkOID(const char * beg, const char * end,
|
||||
const char * oid)
|
||||
{
|
||||
curl_asn1Element e;
|
||||
const char * ccp;
|
||||
const char * p;
|
||||
bool matched;
|
||||
|
||||
/* Check if first ASN.1 element at `beg' is the given OID.
|
||||
Return a pointer in the source after the OID if found, else NULL. */
|
||||
|
||||
ccp = Curl_getASN1Element(&e, beg, end);
|
||||
if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
|
||||
return (const char *) NULL;
|
||||
|
||||
p = OID2str(e.beg, e.end, FALSE);
|
||||
if(!p)
|
||||
return (const char *) NULL;
|
||||
|
||||
matched = !strcmp(p, oid);
|
||||
free((char *) p);
|
||||
return matched? ccp: (const char *) NULL;
|
||||
}
|
||||
|
||||
CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
const char * beg, const char * end)
|
||||
@@ -1178,4 +1180,4 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||
return CURLE_PEER_FAILED_VERIFICATION;
|
||||
}
|
||||
|
||||
#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
|
||||
#endif /* USE_QSOSSL or USE_GSKIT */
|
||||
|
||||
@@ -1182,6 +1182,12 @@
|
||||
d c 10223
|
||||
d CURLOPT_LOGIN_OPTIONS...
|
||||
d c 10224
|
||||
d CURLOPT_SSL_ENABLE_NPN...
|
||||
d c 00225
|
||||
d CURLOPT_SSL_ENABLE_ALPN...
|
||||
d c 00226
|
||||
d CURLOPT_EXPECT_100_TIMEOUT_MS...
|
||||
d c 00227
|
||||
*
|
||||
/if not defined(CURL_NO_OLDIES)
|
||||
d CURLOPT_SSLKEYPASSWD...
|
||||
|
||||
@@ -3,16 +3,32 @@
|
||||
# G. Vanem <gvanem@broadpark.no>
|
||||
#
|
||||
|
||||
.ERASE
|
||||
|
||||
!if $(__VERSION__) < 1280
|
||||
!message !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!message ! This Open Watcom version is too old and is no longer supported !
|
||||
!message ! Please download latest version from www.openwatcom.org !
|
||||
!message !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!error Unsupported version of Open Watcom
|
||||
!endif
|
||||
|
||||
!ifndef %watcom
|
||||
!error WATCOM environment variable not set!
|
||||
!endif
|
||||
|
||||
# In order to process Makefile.inc wmake must be called with -u switch!
|
||||
!ifndef %MAKEFLAGS
|
||||
!error You MUST call wmake with the -u switch!
|
||||
!endif
|
||||
|
||||
!ifdef %libname
|
||||
LIBNAME = $(%libname)
|
||||
!else
|
||||
LIBNAME = libcurl
|
||||
!endif
|
||||
TARGETS = $(LIBNAME).dll $(LIBNAME)_imp.lib $(LIBNAME).lib
|
||||
|
||||
TARGETS = curl.exe
|
||||
|
||||
CC = wcc386
|
||||
LD = wlink
|
||||
@@ -23,37 +39,29 @@ RC = wrc
|
||||
! loaddll wcc386 wccd386
|
||||
! loaddll wpp386 wppd386
|
||||
! loaddll wlib wlibd
|
||||
! if $(__VERSION__) > 1270
|
||||
! loaddll wlink wlinkd
|
||||
! else
|
||||
! loaddll wlink wlink
|
||||
! endif
|
||||
! loaddll wlink wlinkd
|
||||
!endif
|
||||
|
||||
!ifdef __LINUX__
|
||||
DS = /
|
||||
!ifdef __UNIX__
|
||||
CP = cp
|
||||
MD = mkdir -p
|
||||
RD = rmdir -p
|
||||
RM = rm -f
|
||||
!else
|
||||
DS = $(X)\$(X)
|
||||
CP = copy 2>NUL
|
||||
MD = mkdir
|
||||
RD = rmdir /q /s 2>NUL
|
||||
!if $(__VERSION__) < 1250
|
||||
RM = del /q /f 2>NUL
|
||||
!else
|
||||
RM = rm -f
|
||||
!endif
|
||||
!if $(__VERSION__) > 1290
|
||||
RD = rm -rf
|
||||
!else ifdef __UNIX__
|
||||
RD = rm -rf
|
||||
!else
|
||||
RD = rmdir /q /s 2>NUL
|
||||
!endif
|
||||
|
||||
SYS_INCL = -I$(%watcom)$(DS)h$(DS)nt -I$(%watcom)$(DS)h
|
||||
SYS_LIBS = $(%watcom)$(DS)lib386$(DS)nt;$(%watcom)$(DS)lib386
|
||||
SYS_INCL = -I"$(%watcom)/h/nt" -I"$(%watcom)/h"
|
||||
|
||||
CFLAGS = -3r -mf -hc -zff -zgf -zq -zm -s -fr=con -w2 -fpi -oilrtfm &
|
||||
-wcd=201 -bt=nt -bc -d+ -dWIN32 -dHAVE_STRTOLL &
|
||||
-I..$(DS)include -I..$(DS)lib $(SYS_INCL)
|
||||
-I"../include" -I"../lib" $(SYS_INCL)
|
||||
|
||||
!ifdef %debug
|
||||
DEBUG = -dDEBUG=1 -dDEBUGBUILD
|
||||
@@ -66,82 +74,75 @@ CFLAGS += -d0
|
||||
CFLAGS += -d_WIN32_WINNT=0x0501 -dENABLE_IPV6
|
||||
!endif
|
||||
|
||||
!ifdef %use_ssl
|
||||
CFLAGS += -wcd=138 -dUSE_OPENSSL -dUSE_SSLEAY -I"$(OPENSSL_ROOT)/inc32"
|
||||
!endif
|
||||
|
||||
!ifdef %curl_static
|
||||
CFLAGS += -DCURL_STATICLIB
|
||||
!else
|
||||
CFLAGS += -br
|
||||
!endif
|
||||
|
||||
#
|
||||
# Change to suite.
|
||||
#
|
||||
!ifdef %zlib_root
|
||||
ZLIB_ROOT = $(%zlib_root)
|
||||
!else
|
||||
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.8
|
||||
ZLIB_ROOT = ../../zlib-1.2.8
|
||||
!endif
|
||||
|
||||
!ifdef %libssh2_root
|
||||
LIBSSH2_ROOT = $(%libssh2_root)
|
||||
!else
|
||||
LIBSSH2_ROOT = ..$(DS)..$(DS)libssh2-1.4.3
|
||||
LIBSSH2_ROOT = ../../libssh2-1.4.3
|
||||
!endif
|
||||
|
||||
!ifdef %librtmp_root
|
||||
LIBRTMP_ROOT = $(%librtmp_root)
|
||||
!else
|
||||
LIBRTMP_ROOT = ..$(DS)..$(DS)rtmpdump-2.3
|
||||
LIBRTMP_ROOT = ../../rtmpdump-2.3
|
||||
!endif
|
||||
|
||||
!ifdef %openssl_root
|
||||
OPENSSL_ROOT = $(%openssl_root)
|
||||
!else
|
||||
OPENSSL_ROOT = ..$(DS)..$(DS)openssl-0.9.8y
|
||||
OPENSSL_ROOT = ../../openssl-0.9.8y
|
||||
!endif
|
||||
|
||||
!ifdef %ares_root
|
||||
ARES_ROOT = $(%ares_root)
|
||||
!else
|
||||
ARES_ROOT = ..$(DS)ares
|
||||
!endif
|
||||
|
||||
!ifdef %use_ssl
|
||||
CFLAGS += -wcd=138 -dUSE_OPENSSL -dUSE_SSLEAY -I$(OPENSSL_ROOT)$(DS)inc32
|
||||
ARES_ROOT = ../ares
|
||||
!endif
|
||||
|
||||
OBJ_DIR = WC_Win32.obj
|
||||
LINK_ARG = $(OBJ_DIR)$(DS)wlink.arg
|
||||
LINK_ARG = $(OBJ_DIR)/wlink.arg
|
||||
|
||||
# In order to process Makefile.inc wmake must be called with -u switch!
|
||||
!ifndef %MAKEFLAGS
|
||||
!error You MUST call wmake with the -u switch!
|
||||
!else
|
||||
!include Makefile.inc
|
||||
|
||||
OBJS1 = $(OBJ_DIR)/$(CURL_CFILES)
|
||||
!ifndef %curl_static
|
||||
OBJS1 += $(CURLX_ONES:../lib/=)
|
||||
!endif
|
||||
# For now we still define the CURLX_ONES sources here unless we know how
|
||||
# to split off the prefixed path.
|
||||
CURLX_SOURCES = rawstr.c nonblock.c
|
||||
OBJS2 = $(OBJS1: = $(OBJ_DIR)/)
|
||||
OBJS = $(OBJS2:.c=.obj)
|
||||
|
||||
OBJS = $(CURL_CFILES:.c=.obj)
|
||||
!ifdef %curl_static
|
||||
CFLAGS += -DCURL_STATICLIB
|
||||
!else
|
||||
CFLAGS += -br
|
||||
OBJS += $(CURLX_SOURCES:.c=.obj)
|
||||
!endif
|
||||
!ifdef __LINUX__
|
||||
OBJS = $OBJ_DIR/$(OBJS: = $OBJ_DIR/)
|
||||
RESOURCE = $(OBJ_DIR)/curl.res
|
||||
|
||||
!else
|
||||
OBJS = $OBJ_DIR\$(OBJS: = $OBJ_DIR\)
|
||||
!endif
|
||||
DIRS = $(OBJ_DIR)
|
||||
|
||||
RESOURCE = $(OBJ_DIR)$(DS)curl.res
|
||||
|
||||
all: tool_hugehelp.c $(OBJ_DIR) curl.exe .SYMBOLIC
|
||||
all: tool_hugehelp.c $(DIRS) $(TARGETS) .SYMBOLIC
|
||||
@echo Welcome to cURL
|
||||
|
||||
clean: .SYMBOLIC
|
||||
-$(RM) $(OBJS)
|
||||
-$(RM) $(RESOURCE) $(LINK_ARG)
|
||||
-rm -f $(OBJS)
|
||||
-rm -f $(RESOURCE) $(LINK_ARG)
|
||||
|
||||
vclean distclean: clean .SYMBOLIC
|
||||
-$(RD) $(OBJ_DIR)
|
||||
-$(RM) curl.exe curl.map curl.sym tool_hugehelp.c
|
||||
-rm -f curl.exe curl.sym tool_hugehelp.c
|
||||
|
||||
tool_hugehelp.c: tool_hugehelp.c.cvs
|
||||
$(CP) $[@ $^@
|
||||
@@ -149,64 +150,63 @@ tool_hugehelp.c: tool_hugehelp.c.cvs
|
||||
tool_hugehelp.c.cvs: .EXISTSONLY
|
||||
$(CP) tool_hugehelp.c $^@
|
||||
|
||||
$(OBJ_DIR):
|
||||
$(DIRS):
|
||||
-$(MD) $^@
|
||||
|
||||
curl.exe: $(OBJS) $(RESOURCE) $(LINK_ARG)
|
||||
$(LD) name $^@ @$]@
|
||||
|
||||
$(RESOURCE): curl.rc
|
||||
$(RC) $(DEBUG) -q -r -zm -bt=nt -I..$(DS)include $(SYS_INCL) $[@ -fo=$^@
|
||||
|
||||
# suffix search path - vpath-like hack
|
||||
.c: ..$(DS)lib
|
||||
|
||||
.ERASE
|
||||
.c{$(OBJ_DIR)}.obj:
|
||||
$(CC) $(CFLAGS) $[@ -fo=$^@
|
||||
|
||||
$(LINK_ARG): $(__MAKEFILES__)
|
||||
%create $^@
|
||||
@%append $^@ system nt
|
||||
@%append $^@ file { $(OBJS) }
|
||||
curl.exe: $(OBJS) $(RESOURCE)
|
||||
%create $(LINK_ARG)
|
||||
@%append $(LINK_ARG) system nt
|
||||
!ifdef %debug
|
||||
@%append $^@ debug all
|
||||
@%append $^@ option symfile
|
||||
!endif
|
||||
@%append $^@ option quiet, map, caseexact, eliminate,
|
||||
@%append $^@ res=$(RESOURCE) libpath $(SYS_LIBS)
|
||||
!ifdef %curl_static
|
||||
@%append $^@ library wldap32.lib
|
||||
@%append $^@ library ..$(DS)lib$(DS)$(LIBNAME).lib
|
||||
!ifdef %use_zlib
|
||||
@%append $^@ library $(ZLIB_ROOT)$(DS)zlib.lib
|
||||
!endif
|
||||
!ifdef %use_rtmp
|
||||
@%append $^@ library $(LIBRTMP_ROOT)$(DS)librtmp$(DS)librtmp.lib, winmm.lib
|
||||
!endif
|
||||
!ifdef %use_ssh2
|
||||
@%append $^@ library $(LIBSSH2_ROOT)$(DS)win32$(DS)libssh2.lib
|
||||
!endif
|
||||
!ifdef %use_ssl
|
||||
@%append $^@ library $(OPENSSL_ROOT)$(DS)out32$(DS)libeay32.lib, $(OPENSSL_ROOT)$(DS)out32$(DS)ssleay32.lib
|
||||
!endif
|
||||
!ifdef %use_ares
|
||||
@%append $^@ library $(ARES_ROOT)$(DS)cares.lib
|
||||
!endif
|
||||
!ifdef %use_winidn
|
||||
! if $(__VERSION__) > 1290
|
||||
@%append $^@ library normaliz.lib
|
||||
! else
|
||||
@%append $^@ import '_IdnToAscii@20' 'NORMALIZ.DLL'.'IdnToAscii'
|
||||
@%append $^@ import '_IdnToUnicode@20' 'NORMALIZ.DLL'.'IdnToUnicode'
|
||||
! endif
|
||||
@%append $(LINK_ARG) debug all
|
||||
@%append $(LINK_ARG) option symfile
|
||||
!endif
|
||||
@%append $(LINK_ARG) option quiet, caseexact, eliminate
|
||||
@%append $(LINK_ARG) option map=$(OBJ_DIR)/$^&.map
|
||||
@%append $(LINK_ARG) option res=$(RESOURCE)
|
||||
@%append $(LINK_ARG) file { $(OBJS) }
|
||||
!ifndef %curl_static
|
||||
@%append $(LINK_ARG) library ../lib/$(LIBNAME)_imp.lib
|
||||
!else
|
||||
@%append $^@ library ..$(DS)lib$(DS)$(LIBNAME)_imp.lib
|
||||
@%append $(LINK_ARG) library ../lib/$(LIBNAME).lib
|
||||
@%append $(LINK_ARG) library wldap32.lib
|
||||
! ifdef %use_zlib
|
||||
@%append $(LINK_ARG) library '$(ZLIB_ROOT)/zlib.lib'
|
||||
! endif
|
||||
! ifdef %use_rtmp
|
||||
@%append $(LINK_ARG) library '$(LIBRTMP_ROOT)/librtmp/librtmp.lib'
|
||||
@%append $(LINK_ARG) library winmm.lib
|
||||
! endif
|
||||
! ifdef %use_ssh2
|
||||
@%append $(LINK_ARG) library '$(LIBSSH2_ROOT)/win32/libssh2.lib'
|
||||
! endif
|
||||
! ifdef %use_ssl
|
||||
@%append $(LINK_ARG) library '$(OPENSSL_ROOT)/out32/libeay32.lib'
|
||||
@%append $(LINK_ARG) library '$(OPENSSL_ROOT)/out32/ssleay32.lib'
|
||||
! endif
|
||||
! ifdef %use_ares
|
||||
@%append $(LINK_ARG) library '$(ARES_ROOT)/cares.lib'
|
||||
! endif
|
||||
! ifdef %use_winidn
|
||||
! if $(__VERSION__) > 1290
|
||||
@%append $(LINK_ARG) library normaliz.lib
|
||||
! else
|
||||
@%append $(LINK_ARG) import '_IdnToAscii@20' 'NORMALIZ.DLL'.'IdnToAscii'
|
||||
@%append $(LINK_ARG) import '_IdnToUnicode@20' 'NORMALIZ.DLL'.'IdnToUnicode'
|
||||
! endif
|
||||
! endif
|
||||
!endif
|
||||
!ifeq USE_WATT32 1
|
||||
@%append $^@ library $(%watt_root)$(DS)lib$(DS)wattcpw_imp.lib
|
||||
@%append $(LINK_ARG) library '$(%watt_root)/lib/wattcpw_imp.lib'
|
||||
!else
|
||||
@%append $^@ library ws2_32.lib
|
||||
@%append $(LINK_ARG) library ws2_32.lib
|
||||
!endif
|
||||
$(LD) name $^@ @$(LINK_ARG)
|
||||
|
||||
$(RESOURCE): curl.rc
|
||||
$(RC) $(DEBUG) -q -r -zm -bt=nt -I"../include" $(SYS_INCL) $[@ -fo=$^@
|
||||
|
||||
# suffix search path - vpath-like hack
|
||||
.c: ../lib
|
||||
|
||||
.c{$(OBJ_DIR)}.obj:
|
||||
$(CC) $(CFLAGS) $[@ -fo=$^@
|
||||
|
||||
@@ -13,7 +13,8 @@ CURLX_ONES = \
|
||||
../lib/strtoofft.c \
|
||||
../lib/strdup.c \
|
||||
../lib/rawstr.c \
|
||||
../lib/nonblock.c
|
||||
../lib/nonblock.c \
|
||||
../lib/warnless.c
|
||||
|
||||
CURL_CFILES = \
|
||||
tool_binmode.c \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -44,7 +44,8 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||
unsigned char *data, size_t size,
|
||||
void *userdata)
|
||||
{
|
||||
struct Configurable *config = userdata;
|
||||
struct OperationConfig *operation = userdata;
|
||||
struct GlobalConfig *config = operation->global;
|
||||
FILE *output = config->errors;
|
||||
const char *text;
|
||||
struct timeval tv;
|
||||
@@ -87,7 +88,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||
output = config->trace_stream;
|
||||
|
||||
if(!output) {
|
||||
warnf(config, "Failed to create/open output");
|
||||
warnf(operation, "Failed to create/open output");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -141,8 +142,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
|
||||
to stderr or stdout, we don't display the alert about the data not
|
||||
being shown as the data _is_ shown then just not via this
|
||||
function */
|
||||
if(!config->isatty ||
|
||||
((output != stderr) && (output != stdout))) {
|
||||
if(!config->isatty || ((output != stderr) && (output != stdout))) {
|
||||
if(!newl)
|
||||
fprintf(output, "%s%s ", timebuf, s_infotype[type]);
|
||||
fprintf(output, "[data not shown]\n");
|
||||
|
||||
@@ -101,7 +101,7 @@ int tool_progress_cb(void *clientp,
|
||||
}
|
||||
|
||||
void progressbarinit(struct ProgressData *bar,
|
||||
struct Configurable *config)
|
||||
struct OperationConfig *config)
|
||||
{
|
||||
#ifdef __EMX__
|
||||
/* 20000318 mgs */
|
||||
@@ -146,6 +146,5 @@ void progressbarinit(struct ProgressData *bar,
|
||||
bar->width = scr_size[0] - 1;
|
||||
#endif
|
||||
|
||||
bar->out = config->errors;
|
||||
bar->out = config->global->errors;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -36,7 +36,7 @@ struct ProgressData {
|
||||
};
|
||||
|
||||
void progressbarinit(struct ProgressData *bar,
|
||||
struct Configurable *config);
|
||||
struct OperationConfig *config);
|
||||
|
||||
/*
|
||||
** callback for CURLOPT_PROGRESSFUNCTION
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -39,7 +39,7 @@ size_t tool_write_cb(void *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
{
|
||||
size_t rc;
|
||||
struct OutStruct *outs = userdata;
|
||||
struct Configurable *config = outs->config;
|
||||
struct OperationConfig *config = outs->config;
|
||||
|
||||
/*
|
||||
* Once that libcurl has called back tool_write_cb() the returned value
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -22,18 +22,29 @@
|
||||
#include "tool_setup.h"
|
||||
|
||||
#include "tool_cfgable.h"
|
||||
#include "tool_main.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
void free_config_fields(struct Configurable *config)
|
||||
void config_init(struct OperationConfig* config)
|
||||
{
|
||||
memset(config, 0, sizeof(struct OperationConfig));
|
||||
|
||||
config->postfieldsize = -1;
|
||||
config->use_httpget = FALSE;
|
||||
config->create_dirs = FALSE;
|
||||
config->maxredirs = DEFAULT_MAXREDIRS;
|
||||
config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
|
||||
config->proto_present = FALSE;
|
||||
config->proto_redir =
|
||||
CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
|
||||
config->proto_redir_present = FALSE;
|
||||
}
|
||||
|
||||
static void free_config_fields(struct OperationConfig *config)
|
||||
{
|
||||
struct getout *urlnode;
|
||||
|
||||
if(config->easy) {
|
||||
curl_easy_cleanup(config->easy);
|
||||
config->easy = NULL;
|
||||
}
|
||||
|
||||
Curl_safefree(config->random_file);
|
||||
Curl_safefree(config->egd_file);
|
||||
Curl_safefree(config->useragent);
|
||||
@@ -99,16 +110,11 @@ void free_config_fields(struct Configurable *config)
|
||||
|
||||
Curl_safefree(config->customrequest);
|
||||
Curl_safefree(config->krblevel);
|
||||
Curl_safefree(config->trace_dump);
|
||||
|
||||
Curl_safefree(config->xoauth2_bearer);
|
||||
|
||||
config->trace_stream = NULL; /* closed elsewhere when appropriate */
|
||||
|
||||
Curl_safefree(config->writeout);
|
||||
|
||||
config->errors = NULL; /* closed elsewhere when appropriate */
|
||||
|
||||
curl_slist_free_all(config->quote);
|
||||
curl_slist_free_all(config->postquote);
|
||||
curl_slist_free_all(config->prequote);
|
||||
@@ -129,6 +135,19 @@ void free_config_fields(struct Configurable *config)
|
||||
|
||||
Curl_safefree(config->ftp_account);
|
||||
Curl_safefree(config->ftp_alternative_to_user);
|
||||
|
||||
Curl_safefree(config->libcurl);
|
||||
}
|
||||
|
||||
void config_free(struct OperationConfig *config)
|
||||
{
|
||||
struct OperationConfig *last = config;
|
||||
|
||||
/* Free each of the structures in reverse order */
|
||||
while(last) {
|
||||
struct OperationConfig *prev = last->prev;
|
||||
|
||||
free_config_fields(last);
|
||||
free(last);
|
||||
|
||||
last = prev;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -27,8 +27,10 @@
|
||||
|
||||
#include "tool_metalink.h"
|
||||
|
||||
struct Configurable {
|
||||
CURL *easy; /* once we have one, we keep it here */
|
||||
struct GlobalConfig;
|
||||
|
||||
struct OperationConfig {
|
||||
CURL *easy; /* A copy of the handle from GlobalConfig */
|
||||
bool remote_time;
|
||||
char *random_file;
|
||||
char *egd_file;
|
||||
@@ -70,9 +72,6 @@ struct Configurable {
|
||||
char *dns_interface; /* interface name */
|
||||
char *dns_ipv4_addr; /* dot notation */
|
||||
char *dns_ipv6_addr; /* dot notation */
|
||||
int showerror; /* -1 == unset, default => show errors
|
||||
0 => -s is used to NOT show errors
|
||||
1 => -S has been used to show errors */
|
||||
char *userpwd;
|
||||
char *login_options;
|
||||
char *tls_username;
|
||||
@@ -88,7 +87,6 @@ struct Configurable {
|
||||
bool sasl_ir; /* Enable/disable SASL initial response */
|
||||
bool proxytunnel;
|
||||
bool ftp_append; /* APPE on ftp */
|
||||
bool mute; /* don't show messages, --silent given */
|
||||
bool use_ascii; /* select ascii or text transfer */
|
||||
bool autoreferer; /* automatically set referer */
|
||||
bool failonerror; /* fail on (HTTP) errors */
|
||||
@@ -102,8 +100,6 @@ struct Configurable {
|
||||
bool netrc_opt;
|
||||
bool netrc;
|
||||
char *netrc_file;
|
||||
bool noprogress; /* don't show progress meter, --silent given */
|
||||
bool isatty; /* updated internally only if output is a tty */
|
||||
struct getout *url_list; /* point to the first node */
|
||||
struct getout *url_last; /* point to the last/current node */
|
||||
struct getout *url_get; /* point to the node to fill in URL */
|
||||
@@ -120,17 +116,10 @@ struct Configurable {
|
||||
char *pubkey;
|
||||
char *hostpubmd5;
|
||||
char *engine;
|
||||
bool list_engines;
|
||||
bool crlf;
|
||||
char *customrequest;
|
||||
char *krblevel;
|
||||
char *trace_dump; /* file to dump the network trace to, or NULL */
|
||||
FILE *trace_stream;
|
||||
bool trace_fopened;
|
||||
trace tracetype;
|
||||
bool tracetime; /* include timestamp? */
|
||||
long httpversion;
|
||||
int progressmode; /* CURL_PROGRESS_BAR or CURL_PROGRESS_STATS */
|
||||
bool nobuffer;
|
||||
bool readbusy; /* set when reading input returns EAGAIN */
|
||||
bool globoff;
|
||||
@@ -146,8 +135,6 @@ struct Configurable {
|
||||
bool proxyanyauth;
|
||||
char *writeout; /* %-styled format string to output */
|
||||
bool writeenv; /* write results to environment, if available */
|
||||
FILE *errors; /* errors stream, defaults to stderr */
|
||||
bool errors_fopened; /* whether errors stream isn't stderr */
|
||||
struct curl_slist *quote;
|
||||
struct curl_slist *postquote;
|
||||
struct curl_slist *prequote;
|
||||
@@ -191,7 +178,6 @@ struct Configurable {
|
||||
bool ignorecl; /* --ignore-content-length */
|
||||
bool disable_sessionid;
|
||||
|
||||
char *libcurl; /* output libcurl code to this file name */
|
||||
bool raw;
|
||||
bool post301;
|
||||
bool post302;
|
||||
@@ -213,9 +199,39 @@ struct Configurable {
|
||||
#ifdef CURLDEBUG
|
||||
bool test_event_based;
|
||||
#endif
|
||||
char *xoauth2_bearer; /* XOAUTH2 bearer token */
|
||||
}; /* struct Configurable */
|
||||
char *xoauth2_bearer; /* XOAUTH2 bearer token */
|
||||
bool nonpn; /* enable/disable TLS NPN extension */
|
||||
bool noalpn; /* enable/disable TLS ALPN extension */
|
||||
|
||||
void free_config_fields(struct Configurable *config);
|
||||
struct GlobalConfig *global;
|
||||
struct OperationConfig *prev;
|
||||
struct OperationConfig *next; /* Always last in the struct */
|
||||
};
|
||||
|
||||
struct GlobalConfig {
|
||||
CURL *easy; /* Once we have one, we keep it here */
|
||||
int showerror; /* -1 == unset, default => show errors
|
||||
0 => -s is used to NOT show errors
|
||||
1 => -S has been used to show errors */
|
||||
bool mute; /* don't show messages, --silent given */
|
||||
bool noprogress; /* don't show progress bar --silent given */
|
||||
bool isatty; /* Updated internally if output is a tty */
|
||||
FILE *errors; /* Error stream, defaults to stderr */
|
||||
bool errors_fopened; /* Whether error stream isn't stderr */
|
||||
char *trace_dump; /* file to dump the network trace to */
|
||||
FILE *trace_stream;
|
||||
bool trace_fopened;
|
||||
trace tracetype;
|
||||
bool tracetime; /* include timestamp? */
|
||||
int progressmode; /* CURL_PROGRESS_BAR / CURL_PROGRESS_STATS */
|
||||
char *libcurl; /* Output libcurl code to this file name */
|
||||
|
||||
struct OperationConfig *first;
|
||||
struct OperationConfig *current;
|
||||
struct OperationConfig *last; /* Always last in the struct */
|
||||
};
|
||||
|
||||
void config_init(struct OperationConfig *config);
|
||||
void config_free(struct OperationConfig *config);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_CFGABLE_H */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -262,7 +262,8 @@ char **__crt0_glob_function(char *arg)
|
||||
* HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode
|
||||
*/
|
||||
|
||||
CURLcode FindWin32CACert(struct Configurable *config, const char *bundle_file)
|
||||
CURLcode FindWin32CACert(struct OperationConfig *config,
|
||||
const char *bundle_file)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
@@ -296,4 +297,3 @@ CURLcode FindWin32CACert(struct Configurable *config, const char *bundle_file)
|
||||
#endif /* WIN32 */
|
||||
|
||||
#endif /* MSDOS || WIN32 */
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -35,7 +35,8 @@ char **__crt0_glob_function(char *arg);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
CURLcode FindWin32CACert(struct Configurable *config, const char *bundle_file);
|
||||
CURLcode FindWin32CACert(struct OperationConfig *config,
|
||||
const char *bundle_file);
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -154,18 +154,20 @@ CURLcode easysrc_perform(void)
|
||||
|
||||
CHKRET(easysrc_add(&easysrc_code, ""));
|
||||
CHKRET(easysrc_add(&easysrc_code, "ret = curl_easy_perform(hnd);"));
|
||||
CHKRET(easysrc_add(&easysrc_code, ""));
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode easysrc_cleanup(void)
|
||||
{
|
||||
CHKRET(easysrc_add(&easysrc_code, ""));
|
||||
CHKRET(easysrc_add(&easysrc_code, "curl_easy_cleanup(hnd);"));
|
||||
CHKRET(easysrc_add(&easysrc_code, "hnd = NULL;"));
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void dumpeasysrc(struct Configurable *config)
|
||||
void dumpeasysrc(struct GlobalConfig *config)
|
||||
{
|
||||
struct curl_slist *ptr;
|
||||
char *o = config->libcurl;
|
||||
@@ -180,7 +182,7 @@ void dumpeasysrc(struct Configurable *config)
|
||||
else
|
||||
out = stdout;
|
||||
if(!out)
|
||||
warnf(config, "Failed to open %s to write libcurl code!\n", o);
|
||||
warnf(config->current, "Failed to open %s to write libcurl code!\n", o);
|
||||
else {
|
||||
int i;
|
||||
const char *c;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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,7 +40,8 @@ extern CURLcode easysrc_add(struct curl_slist **plist, const char *bupf);
|
||||
extern CURLcode easysrc_addf(struct curl_slist **plist, const char *fmt, ...);
|
||||
extern CURLcode easysrc_perform(void);
|
||||
extern CURLcode easysrc_cleanup(void);
|
||||
void dumpeasysrc(struct Configurable *config);
|
||||
|
||||
void dumpeasysrc(struct GlobalConfig *config);
|
||||
|
||||
#endif /* CURL_DISABLE_LIBCURL_OPTION */
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ static char *get_param_word(char **str, char **end_pos)
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
int formparse(struct Configurable *config,
|
||||
int formparse(struct OperationConfig *config,
|
||||
const char *input,
|
||||
struct curl_httppost **httppost,
|
||||
struct curl_httppost **last_post,
|
||||
@@ -163,7 +163,7 @@ int formparse(struct Configurable *config,
|
||||
/* Allocate the contents */
|
||||
contents = strdup(contp+1);
|
||||
if(!contents) {
|
||||
fprintf(config->errors, "out of memory\n");
|
||||
fprintf(config->global->errors, "out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
contp = contents;
|
||||
@@ -277,7 +277,7 @@ int formparse(struct Configurable *config,
|
||||
}
|
||||
forms = malloc((count+1)*sizeof(struct curl_forms));
|
||||
if(!forms) {
|
||||
fprintf(config->errors, "Error building form post!\n");
|
||||
fprintf(config->global->errors, "Error building form post!\n");
|
||||
Curl_safefree(contents);
|
||||
FreeMultiInfo(&multi_start, &multi_current);
|
||||
return 4;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -23,7 +23,7 @@
|
||||
***************************************************************************/
|
||||
#include "tool_setup.h"
|
||||
|
||||
int formparse(struct Configurable *config,
|
||||
int formparse(struct OperationConfig *config,
|
||||
const char *input,
|
||||
struct curl_httppost **httppost,
|
||||
struct curl_httppost **last_post,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -27,23 +27,17 @@
|
||||
/* use our own printf() functions */
|
||||
#include "curlx.h"
|
||||
|
||||
#ifdef USE_MANUAL
|
||||
# include "tool_hugehelp.h"
|
||||
#endif
|
||||
|
||||
#include "tool_binmode.h"
|
||||
#include "tool_cfgable.h"
|
||||
#include "tool_cb_prg.h"
|
||||
#include "tool_formparse.h"
|
||||
#include "tool_getparam.h"
|
||||
#include "tool_help.h"
|
||||
#include "tool_helpers.h"
|
||||
#include "tool_libinfo.h"
|
||||
#include "tool_metalink.h"
|
||||
#include "tool_msgs.h"
|
||||
#include "tool_paramhlp.h"
|
||||
#include "tool_parsecfg.h"
|
||||
#include "tool_version.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
@@ -90,7 +84,9 @@ static const struct LongShort aliases[]= {
|
||||
#endif
|
||||
{"*F", "dns-servers", TRUE},
|
||||
{"*g", "trace", TRUE},
|
||||
{"*G", "npn", FALSE},
|
||||
{"*h", "trace-ascii", TRUE},
|
||||
{"*H", "alpn", FALSE},
|
||||
{"*i", "limit-rate", TRUE},
|
||||
{"*j", "compressed", FALSE},
|
||||
{"*J", "tr-encoding", FALSE},
|
||||
@@ -182,7 +178,7 @@ static const struct LongShort aliases[]= {
|
||||
{"$L", "test-event", FALSE},
|
||||
{"0", "http1.0", FALSE},
|
||||
{"01", "http1.1", FALSE},
|
||||
{"02", "http2.0", FALSE},
|
||||
{"02", "http2", FALSE},
|
||||
{"1", "tlsv1", FALSE},
|
||||
{"10", "tlsv1.0", FALSE},
|
||||
{"11", "tlsv1.1", FALSE},
|
||||
@@ -271,34 +267,10 @@ static const struct LongShort aliases[]= {
|
||||
{"y", "speed-time", TRUE},
|
||||
{"z", "time-cond", TRUE},
|
||||
{"#", "progress-bar", FALSE},
|
||||
{":", "next", FALSE},
|
||||
{"~", "xattr", FALSE},
|
||||
};
|
||||
|
||||
struct feat {
|
||||
const char *name;
|
||||
int bitmask;
|
||||
};
|
||||
|
||||
static const struct feat feats[] = {
|
||||
{"AsynchDNS", CURL_VERSION_ASYNCHDNS},
|
||||
{"Debug", CURL_VERSION_DEBUG},
|
||||
{"TrackMemory", CURL_VERSION_CURLDEBUG},
|
||||
{"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
|
||||
{"IDN", CURL_VERSION_IDN},
|
||||
{"IPv6", CURL_VERSION_IPV6},
|
||||
{"Largefile", CURL_VERSION_LARGEFILE},
|
||||
{"NTLM", CURL_VERSION_NTLM},
|
||||
{"NTLM_WB", CURL_VERSION_NTLM_WB},
|
||||
{"SPNEGO", CURL_VERSION_SPNEGO},
|
||||
{"SSL", CURL_VERSION_SSL},
|
||||
{"SSPI", CURL_VERSION_SSPI},
|
||||
{"krb4", CURL_VERSION_KERBEROS4},
|
||||
{"libz", CURL_VERSION_LIBZ},
|
||||
{"CharConv", CURL_VERSION_CONV},
|
||||
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
|
||||
{"HTTP2", CURL_VERSION_HTTP2}
|
||||
};
|
||||
|
||||
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
|
||||
* We allow ':' and '\' to be escaped by '\' so that we can use certificate
|
||||
* nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
|
||||
@@ -402,7 +374,8 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
char *nextarg, /* NULL if unset */
|
||||
bool *usedarg, /* set to TRUE if the arg
|
||||
has been used */
|
||||
struct Configurable *config)
|
||||
struct GlobalConfig *global,
|
||||
struct OperationConfig *config)
|
||||
{
|
||||
char letter;
|
||||
char subletter = '\0'; /* subletters can only occur on long options */
|
||||
@@ -549,17 +522,23 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
GetStr(&config->dns_servers, nextarg);
|
||||
break;
|
||||
case 'g': /* --trace */
|
||||
GetStr(&config->trace_dump, nextarg);
|
||||
if(config->tracetype && (config->tracetype != TRACE_BIN))
|
||||
GetStr(&global->trace_dump, nextarg);
|
||||
if(global->tracetype && (global->tracetype != TRACE_BIN))
|
||||
warnf(config, "--trace overrides an earlier trace/verbose option\n");
|
||||
config->tracetype = TRACE_BIN;
|
||||
global->tracetype = TRACE_BIN;
|
||||
break;
|
||||
case 'G': /* --npn */
|
||||
config->nonpn = (!toggle)?TRUE:FALSE;
|
||||
break;
|
||||
case 'h': /* --trace-ascii */
|
||||
GetStr(&config->trace_dump, nextarg);
|
||||
if(config->tracetype && (config->tracetype != TRACE_ASCII))
|
||||
GetStr(&global->trace_dump, nextarg);
|
||||
if(global->tracetype && (global->tracetype != TRACE_ASCII))
|
||||
warnf(config,
|
||||
"--trace-ascii overrides an earlier trace/verbose option\n");
|
||||
config->tracetype = TRACE_ASCII;
|
||||
global->tracetype = TRACE_ASCII;
|
||||
break;
|
||||
case 'H': /* --alpn */
|
||||
config->noalpn = (!toggle)?TRUE:FALSE;
|
||||
break;
|
||||
case 'i': /* --limit-rate */
|
||||
{
|
||||
@@ -702,14 +681,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
if(!newfile)
|
||||
warnf(config, "Failed to open %s!\n", nextarg);
|
||||
else {
|
||||
if(config->errors_fopened)
|
||||
fclose(config->errors);
|
||||
config->errors = newfile;
|
||||
config->errors_fopened = TRUE;
|
||||
if(global->errors_fopened)
|
||||
fclose(global->errors);
|
||||
global->errors = newfile;
|
||||
global->errors_fopened = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
config->errors = stdout;
|
||||
global->errors = stdout;
|
||||
break;
|
||||
case 'w': /* --interface */
|
||||
/* interface */
|
||||
@@ -830,7 +809,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
config->proxyanyauth = toggle;
|
||||
break;
|
||||
case 'o': /* --trace-time */
|
||||
config->tracetime = toggle;
|
||||
global->tracetime = toggle;
|
||||
break;
|
||||
case 'p': /* --ignore-content-length */
|
||||
config->ignorecl = toggle;
|
||||
@@ -888,7 +867,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
"--libcurl option was disabled at build-time!\n");
|
||||
return PARAM_OPTION_UNKNOWN;
|
||||
#else
|
||||
GetStr(&config->libcurl, nextarg);
|
||||
GetStr(&global->libcurl, nextarg);
|
||||
break;
|
||||
#endif
|
||||
case '#': /* --raw */
|
||||
@@ -1004,10 +983,12 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
break;
|
||||
case '#': /* --progress-bar */
|
||||
if(toggle)
|
||||
config->progressmode = CURL_PROGRESS_BAR;
|
||||
global->progressmode = CURL_PROGRESS_BAR;
|
||||
else
|
||||
config->progressmode = CURL_PROGRESS_STATS;
|
||||
global->progressmode = CURL_PROGRESS_STATS;
|
||||
break;
|
||||
case ':': /* --next */
|
||||
return PARAM_NEXT_OPERATION;
|
||||
case '~': /* --xattr */
|
||||
config->xattr = toggle;
|
||||
break;
|
||||
@@ -1328,7 +1309,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'f': /* crypto engine */
|
||||
GetStr(&config->engine, nextarg);
|
||||
if(config->engine && curlx_raw_equal(config->engine,"list"))
|
||||
config->list_engines = TRUE;
|
||||
return PARAM_ENGINES_REQUESTED;
|
||||
break;
|
||||
case 'g': /* CA info PEM file */
|
||||
/* CA cert directory */
|
||||
@@ -1417,7 +1398,6 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
|
||||
case 'h': /* h for help */
|
||||
if(toggle) {
|
||||
tool_help();
|
||||
return PARAM_HELP_REQUESTED;
|
||||
}
|
||||
/* we now actually support --no-help too! */
|
||||
@@ -1457,7 +1437,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
config->insecure_ok = toggle;
|
||||
break;
|
||||
case 'K': /* parse config file */
|
||||
if(parseconfig(nextarg, config))
|
||||
if(parseconfig(nextarg, global))
|
||||
warnf(config, "error trying read config from the '%s' file\n",
|
||||
nextarg);
|
||||
break;
|
||||
@@ -1483,8 +1463,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'M': /* M for manual, huge help */
|
||||
if(toggle) { /* --no-manual shows no manual... */
|
||||
#ifdef USE_MANUAL
|
||||
hugehelp();
|
||||
return PARAM_HELP_REQUESTED;
|
||||
return PARAM_MANUAL_REQUESTED;
|
||||
#else
|
||||
warnf(config,
|
||||
"built-in manual was disabled at build-time!\n");
|
||||
@@ -1640,18 +1619,18 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 's':
|
||||
/* don't show progress meter, don't show errors : */
|
||||
if(toggle)
|
||||
config->mute = config->noprogress = TRUE;
|
||||
global->mute = global->noprogress = TRUE;
|
||||
else
|
||||
config->mute = config->noprogress = FALSE;
|
||||
if(config->showerror < 0)
|
||||
global->mute = global->noprogress = FALSE;
|
||||
if(global->showerror < 0)
|
||||
/* if still on the default value, set showerror to the reverse of
|
||||
toggle. This is to allow -S and -s to be used in an independent
|
||||
order but still have the same effect. */
|
||||
config->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
|
||||
global->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
|
||||
break;
|
||||
case 'S':
|
||||
/* show errors */
|
||||
config->showerror = toggle?1:0; /* toggle on if used with -s */
|
||||
global->showerror = toggle?1:0; /* toggle on if used with -s */
|
||||
break;
|
||||
case 't':
|
||||
/* Telnet options */
|
||||
@@ -1705,49 +1684,24 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
case 'v':
|
||||
if(toggle) {
|
||||
/* the '%' thing here will cause the trace get sent to stderr */
|
||||
Curl_safefree(config->trace_dump);
|
||||
config->trace_dump = strdup("%");
|
||||
if(!config->trace_dump)
|
||||
Curl_safefree(global->trace_dump);
|
||||
global->trace_dump = strdup("%");
|
||||
if(!global->trace_dump)
|
||||
return PARAM_NO_MEM;
|
||||
if(config->tracetype && (config->tracetype != TRACE_PLAIN))
|
||||
if(global->tracetype && (global->tracetype != TRACE_PLAIN))
|
||||
warnf(config,
|
||||
"-v, --verbose overrides an earlier trace/verbose option\n");
|
||||
config->tracetype = TRACE_PLAIN;
|
||||
global->tracetype = TRACE_PLAIN;
|
||||
}
|
||||
else
|
||||
/* verbose is disabled here */
|
||||
config->tracetype = TRACE_NONE;
|
||||
global->tracetype = TRACE_NONE;
|
||||
break;
|
||||
case 'V':
|
||||
{
|
||||
const char *const *proto;
|
||||
if(toggle) /* --no-version yields no output! */
|
||||
return PARAM_VERSION_INFO_REQUESTED;
|
||||
break;
|
||||
|
||||
if(!toggle)
|
||||
/* --no-version yields no output! */
|
||||
break;
|
||||
|
||||
printf(CURL_ID "%s\n", curl_version());
|
||||
if(curlinfo->protocols) {
|
||||
printf("Protocols: ");
|
||||
for(proto = curlinfo->protocols; *proto; ++proto) {
|
||||
printf("%s ", *proto);
|
||||
}
|
||||
puts(""); /* newline */
|
||||
}
|
||||
if(curlinfo->features) {
|
||||
unsigned int i;
|
||||
printf("Features: ");
|
||||
for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
|
||||
if(curlinfo->features & feats[i].bitmask)
|
||||
printf("%s ", feats[i].name);
|
||||
}
|
||||
#ifdef USE_METALINK
|
||||
printf("Metalink ");
|
||||
#endif
|
||||
puts(""); /* newline */
|
||||
}
|
||||
}
|
||||
return PARAM_HELP_REQUESTED;
|
||||
case 'w':
|
||||
/* get the output string */
|
||||
if('@' == *nextarg) {
|
||||
@@ -1847,3 +1801,85 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
|
||||
return PARAM_OK;
|
||||
}
|
||||
|
||||
ParameterError parse_args(struct GlobalConfig *config, int argc,
|
||||
argv_item_t argv[])
|
||||
{
|
||||
int i;
|
||||
bool stillflags;
|
||||
char *orig_opt;
|
||||
ParameterError result = PARAM_OK;
|
||||
struct OperationConfig *operation = config->first;
|
||||
|
||||
for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
|
||||
orig_opt = argv[i];
|
||||
|
||||
if(stillflags && ('-' == argv[i][0])) {
|
||||
char *nextarg;
|
||||
bool passarg;
|
||||
char *flag = argv[i];
|
||||
|
||||
if(curlx_strequal("--", argv[i]))
|
||||
/* This indicates the end of the flags and thus enables the
|
||||
following (URL) argument to start with -. */
|
||||
stillflags = FALSE;
|
||||
else {
|
||||
nextarg = (i < (argc - 1)) ? argv[i + 1] : NULL;
|
||||
|
||||
result = getparameter(flag, nextarg, &passarg, config, operation);
|
||||
if(result == PARAM_NEXT_OPERATION) {
|
||||
/* Reset result as PARAM_NEXT_OPERATION is only used here and not
|
||||
returned from this function */
|
||||
result = PARAM_OK;
|
||||
|
||||
if(operation->url_list && operation->url_list->url) {
|
||||
/* Allocate the next config */
|
||||
operation->next = malloc(sizeof(struct OperationConfig));
|
||||
if(operation->next) {
|
||||
/* Initialise the newly created config */
|
||||
config_init(operation->next);
|
||||
|
||||
/* Copy the easy handle */
|
||||
operation->next->easy = config->easy;
|
||||
|
||||
/* Set the global config pointer */
|
||||
operation->next->global = config;
|
||||
|
||||
/* Update the last operation pointer */
|
||||
config->last = operation->next;
|
||||
|
||||
/* Move onto the new config */
|
||||
operation->next->prev = operation;
|
||||
operation = operation->next;
|
||||
}
|
||||
else
|
||||
result = PARAM_NO_MEM;
|
||||
}
|
||||
}
|
||||
else if(!result && passarg)
|
||||
i++; /* we're supposed to skip this */
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool used;
|
||||
|
||||
/* Just add the URL please */
|
||||
result = getparameter((char *)"--url", argv[i], &used, config,
|
||||
operation);
|
||||
}
|
||||
}
|
||||
|
||||
if(result && result != PARAM_HELP_REQUESTED &&
|
||||
result != PARAM_MANUAL_REQUESTED &&
|
||||
result != PARAM_VERSION_INFO_REQUESTED &&
|
||||
result != PARAM_ENGINES_REQUESTED) {
|
||||
const char *reason = param2text(result);
|
||||
|
||||
if(!curlx_strequal(":", orig_opt))
|
||||
helpf(config->errors, "option %s: %s\n", orig_opt, reason);
|
||||
else
|
||||
helpf(config->errors, "%s\n", reason);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -30,20 +30,24 @@ typedef enum {
|
||||
PARAM_REQUIRES_PARAMETER,
|
||||
PARAM_BAD_USE,
|
||||
PARAM_HELP_REQUESTED,
|
||||
PARAM_MANUAL_REQUESTED,
|
||||
PARAM_VERSION_INFO_REQUESTED,
|
||||
PARAM_ENGINES_REQUESTED,
|
||||
PARAM_GOT_EXTRA_PARAMETER,
|
||||
PARAM_BAD_NUMERIC,
|
||||
PARAM_NEGATIVE_NUMERIC,
|
||||
PARAM_LIBCURL_DOESNT_SUPPORT,
|
||||
PARAM_NO_MEM,
|
||||
PARAM_NEXT_OPERATION,
|
||||
PARAM_LAST
|
||||
} ParameterError;
|
||||
|
||||
struct Configurable;
|
||||
struct GlobalConfig;
|
||||
struct OperationConfig;
|
||||
|
||||
ParameterError getparameter(char *flag,
|
||||
char *nextarg,
|
||||
bool *usedarg,
|
||||
struct Configurable *config);
|
||||
ParameterError getparameter(char *flag, char *nextarg, bool *usedarg,
|
||||
struct GlobalConfig *global,
|
||||
struct OperationConfig *operation);
|
||||
|
||||
#ifdef UNITTESTS
|
||||
void parse_cert_parameter(const char *cert_parameter,
|
||||
@@ -51,5 +55,8 @@ void parse_cert_parameter(const char *cert_parameter,
|
||||
char **passphrase);
|
||||
#endif
|
||||
|
||||
ParameterError parse_args(struct GlobalConfig *config, int argc,
|
||||
argv_item_t argv[]);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_GETPARAM_H */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "tool_panykey.h"
|
||||
#include "tool_help.h"
|
||||
#include "tool_libinfo.h"
|
||||
#include "tool_version.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
@@ -104,7 +106,7 @@ static const char *const helptext[] = {
|
||||
"Hex encoded MD5 string of the host public key. (SSH)",
|
||||
" -0, --http1.0 Use HTTP 1.0 (H)",
|
||||
" --http1.1 Use HTTP 1.1 (H)",
|
||||
" --http2.0 Use HTTP 2.0 (H)",
|
||||
" --http2 Use HTTP 2 (H)",
|
||||
" --ignore-content-length Ignore the HTTP Content-Length header",
|
||||
" -i, --include Include protocol headers in the output (H/F)",
|
||||
" -k, --insecure Allow connections to SSL sites without certs (H)",
|
||||
@@ -136,8 +138,12 @@ static const char *const helptext[] = {
|
||||
" -n, --netrc Must read .netrc for user name and password",
|
||||
" --netrc-optional Use either .netrc or URL; overrides -n",
|
||||
" --netrc-file FILE Set up the netrc filename to use",
|
||||
" -: --next "
|
||||
"Allows the following URL to use a separate set of options",
|
||||
" --no-alpn Disable the ALPN TLS extension (H)",
|
||||
" -N, --no-buffer Disable buffering of the output stream",
|
||||
" --no-keepalive Disable keepalive use on the connection",
|
||||
" --no-npn Disable the NPN TLS extension (H)",
|
||||
" --no-sessionid Disable SSL session-ID reusing (SSL)",
|
||||
" --noproxy List of hosts which do not use proxy",
|
||||
" --ntlm Use HTTP NTLM authentication (H)",
|
||||
@@ -207,7 +213,10 @@ static const char *const helptext[] = {
|
||||
" -t, --telnet-option OPT=VAL Set telnet option",
|
||||
" --tftp-blksize VALUE Set TFTP BLKSIZE option (must be >512)",
|
||||
" -z, --time-cond TIME Transfer based on a time condition",
|
||||
" -1, --tlsv1 Use TLSv1 (SSL)",
|
||||
" -1, --tlsv1 Use => TLSv1 (SSL)",
|
||||
" --tlsv1.0 Use TLSv1.0 (SSL)",
|
||||
" --tlsv1.1 Use TLSv1.1 (SSL)",
|
||||
" --tlsv1.2 Use TLSv1.2 (SSL)",
|
||||
" --trace FILE Write a debug trace to the given file",
|
||||
" --trace-ascii FILE Like --trace but without the hex output",
|
||||
" --trace-time Add time stamps to trace/verbose output",
|
||||
@@ -240,6 +249,31 @@ static const char *const helptext[] = {
|
||||
# define PRINT_LINES_PAUSE 16
|
||||
#endif
|
||||
|
||||
struct feat {
|
||||
const char *name;
|
||||
int bitmask;
|
||||
};
|
||||
|
||||
static const struct feat feats[] = {
|
||||
{"AsynchDNS", CURL_VERSION_ASYNCHDNS},
|
||||
{"Debug", CURL_VERSION_DEBUG},
|
||||
{"TrackMemory", CURL_VERSION_CURLDEBUG},
|
||||
{"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
|
||||
{"IDN", CURL_VERSION_IDN},
|
||||
{"IPv6", CURL_VERSION_IPV6},
|
||||
{"Largefile", CURL_VERSION_LARGEFILE},
|
||||
{"NTLM", CURL_VERSION_NTLM},
|
||||
{"NTLM_WB", CURL_VERSION_NTLM_WB},
|
||||
{"SPNEGO", CURL_VERSION_SPNEGO},
|
||||
{"SSL", CURL_VERSION_SSL},
|
||||
{"SSPI", CURL_VERSION_SSPI},
|
||||
{"krb4", CURL_VERSION_KERBEROS4},
|
||||
{"libz", CURL_VERSION_LIBZ},
|
||||
{"CharConv", CURL_VERSION_CONV},
|
||||
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
|
||||
{"HTTP2", CURL_VERSION_HTTP2}
|
||||
};
|
||||
|
||||
void tool_help(void)
|
||||
{
|
||||
int i;
|
||||
@@ -251,3 +285,49 @@ void tool_help(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void tool_version_info(void)
|
||||
{
|
||||
const char *const *proto;
|
||||
|
||||
printf(CURL_ID "%s\n", curl_version());
|
||||
if(curlinfo->protocols) {
|
||||
printf("Protocols: ");
|
||||
for(proto = curlinfo->protocols; *proto; ++proto) {
|
||||
printf("%s ", *proto);
|
||||
}
|
||||
puts(""); /* newline */
|
||||
}
|
||||
if(curlinfo->features) {
|
||||
unsigned int i;
|
||||
printf("Features: ");
|
||||
for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
|
||||
if(curlinfo->features & feats[i].bitmask)
|
||||
printf("%s ", feats[i].name);
|
||||
}
|
||||
#ifdef USE_METALINK
|
||||
printf("Metalink ");
|
||||
#endif
|
||||
puts(""); /* newline */
|
||||
}
|
||||
}
|
||||
|
||||
void tool_list_engines(CURL *curl)
|
||||
{
|
||||
struct curl_slist *engines = NULL;
|
||||
|
||||
/* Get the list of engines */
|
||||
curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
|
||||
|
||||
puts("Build-time engines:");
|
||||
if(engines) {
|
||||
for(; engines; engines = engines->next)
|
||||
printf(" %s\n", engines->data);
|
||||
}
|
||||
else {
|
||||
puts(" <none>");
|
||||
}
|
||||
|
||||
/* Cleanup the list of engines */
|
||||
curl_slist_free_all(engines);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "tool_setup.h"
|
||||
|
||||
void tool_help(void);
|
||||
void tool_list_engines(CURL *curl);
|
||||
void tool_version_info(void);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_HELP_H */
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
@@ -65,7 +65,7 @@ const char *param2text(int res)
|
||||
}
|
||||
}
|
||||
|
||||
int SetHTTPrequest(struct Configurable *config, HttpReq req, HttpReq *store)
|
||||
int SetHTTPrequest(struct OperationConfig *config, HttpReq req, HttpReq *store)
|
||||
{
|
||||
if((*store == HTTPREQ_UNSPEC) ||
|
||||
(*store == req)) {
|
||||
@@ -75,4 +75,3 @@ int SetHTTPrequest(struct Configurable *config, HttpReq req, HttpReq *store)
|
||||
warnf(config, "You can only select one HTTP request!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
@@ -25,7 +25,8 @@
|
||||
|
||||
const char *param2text(int res);
|
||||
|
||||
int SetHTTPrequest(struct Configurable *config, HttpReq req, HttpReq *store);
|
||||
int SetHTTPrequest(struct OperationConfig *config, HttpReq req,
|
||||
HttpReq *store);
|
||||
|
||||
#endif /* HEADER_CURL_TOOL_HELPERS_H */
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2014, 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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user