Compare commits
200 Commits
curl-7_30_
...
curl-7_31_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85c710e11e | ||
|
|
0de7249bb3 | ||
|
|
192c4f788d | ||
|
|
da0db499fd | ||
|
|
88c5c63ffc | ||
|
|
a9f5ad0e2a | ||
|
|
e305f5ec71 | ||
|
|
7ac3e9f1ba | ||
|
|
03a3dd9ee3 | ||
|
|
5fc24a5297 | ||
|
|
b1a295ac4e | ||
|
|
1826c768ab | ||
|
|
9c3e098259 | ||
|
|
0feeab7802 | ||
|
|
f24dc09d20 | ||
|
|
9e10963c20 | ||
|
|
10b6d81c64 | ||
|
|
8026bd7abd | ||
|
|
9b8df58169 | ||
|
|
529a2e9110 | ||
|
|
21091549c0 | ||
|
|
7b97f03f09 | ||
|
|
ce362e8eb9 | ||
|
|
a4decb49a6 | ||
|
|
c53fb36b0c | ||
|
|
dc19e656b5 | ||
|
|
87cf677eca | ||
|
|
5657c56f63 | ||
|
|
51b3445e84 | ||
|
|
a7452b8b8c | ||
|
|
0bf5ce77aa | ||
|
|
159d34b58e | ||
|
|
29bf0598aa | ||
|
|
239b58d34d | ||
|
|
74f1810546 | ||
|
|
f4b08b8f40 | ||
|
|
6691fdf517 | ||
|
|
7d8d2a54ba | ||
|
|
9986c6cb2b | ||
|
|
ba9a66663a | ||
|
|
ac419bf562 | ||
|
|
520833cbe1 | ||
|
|
e58d9c87f7 | ||
|
|
84f7991474 | ||
|
|
85b9dc8023 | ||
|
|
7d4d4892d8 | ||
|
|
fc4759af9d | ||
|
|
ee84c47655 | ||
|
|
ce32176db7 | ||
|
|
04f52e9b4d | ||
|
|
100a33f7ff | ||
|
|
7ed25ccf0d | ||
|
|
01eede2662 | ||
|
|
ae26ee3489 | ||
|
|
992bee504d | ||
|
|
01a2abedd7 | ||
|
|
a45e3f93e4 | ||
|
|
bdb396ef2a | ||
|
|
6add1901a1 | ||
|
|
51b0f09b5e | ||
|
|
8dac7be438 | ||
|
|
bcf1b9dec1 | ||
|
|
b045d079f8 | ||
|
|
683f2b8323 | ||
|
|
2de20dd9a1 | ||
|
|
b47cf4f688 | ||
|
|
a15b2b6c62 | ||
|
|
42e01cff9a | ||
|
|
865d4138a0 | ||
|
|
35874298e4 | ||
|
|
52d72e66c2 | ||
|
|
f3d10aa0d4 | ||
|
|
7632bc911b | ||
|
|
92ef5f19c8 | ||
|
|
99b4045183 | ||
|
|
087f9bb20a | ||
|
|
e2c7e19144 | ||
|
|
f5c3d95384 | ||
|
|
6b10f5b963 | ||
|
|
ee74b77d45 | ||
|
|
734bdb68c2 | ||
|
|
514817669e | ||
|
|
cb9c0ac7d7 | ||
|
|
1c435295b8 | ||
|
|
46d26a0e77 | ||
|
|
f4e3cae8a7 | ||
|
|
b52cf5d2cd | ||
|
|
073e83b543 | ||
|
|
c3e6d69acb | ||
|
|
b56e3d43e5 | ||
|
|
f317ffb7bb | ||
|
|
9ea5145952 | ||
|
|
1d7c38e1f0 | ||
|
|
18bfc8f2d7 | ||
|
|
945246988d | ||
|
|
a5c0e20939 | ||
|
|
128517649c | ||
|
|
219358b93d | ||
|
|
f133719f73 | ||
|
|
f4e6e201b1 | ||
|
|
790b2086d7 | ||
|
|
f9b691cdb0 | ||
|
|
4118c30261 | ||
|
|
dacbdaab94 | ||
|
|
70e30f6caa | ||
|
|
7cb6c31370 | ||
|
|
5d3a031ca7 | ||
|
|
a846fbbe2a | ||
|
|
6420672879 | ||
|
|
c4067a5678 | ||
|
|
0523152ad6 | ||
|
|
b37b5233ca | ||
|
|
c68c7e588e | ||
|
|
1498a0073e | ||
|
|
27777949a0 | ||
|
|
4dc2d965d6 | ||
|
|
70bbbccc39 | ||
|
|
0dd470fc61 | ||
|
|
89acdf50fa | ||
|
|
c0d502785f | ||
|
|
a8c92cb608 | ||
|
|
53fda844cc | ||
|
|
bbf63b0faa | ||
|
|
2af9fd4960 | ||
|
|
2c0d65785f | ||
|
|
d791179d7f | ||
|
|
c49ed0b6c0 | ||
|
|
868d8e6831 | ||
|
|
e3aca1b2ce | ||
|
|
ddac43b38e | ||
|
|
416ecc1584 | ||
|
|
455ba691a7 | ||
|
|
11332577b3 | ||
|
|
702b0dd408 | ||
|
|
e8a9f794f0 | ||
|
|
bddf3d4705 | ||
|
|
e99c81a07c | ||
|
|
fe880475ed | ||
|
|
5821d5f111 | ||
|
|
d535c4a2e1 | ||
|
|
ca8f17a303 | ||
|
|
fddb7b44a7 | ||
|
|
49184c3723 | ||
|
|
cc7f6a2ddf | ||
|
|
90fe59b829 | ||
|
|
7b074a460b | ||
|
|
993cdcd6ee | ||
|
|
8763374f0e | ||
|
|
63388fe1f3 | ||
|
|
b75a88aa72 | ||
|
|
bb20989a63 | ||
|
|
0d49e408a4 | ||
|
|
90c87f311e | ||
|
|
da06ac7f3f | ||
|
|
6d9236e805 | ||
|
|
c306d2e42f | ||
|
|
f737e3a3dd | ||
|
|
686586b0f9 | ||
|
|
e621a5f6ea | ||
|
|
8093f9541e | ||
|
|
68e7fb499d | ||
|
|
d9569720dd | ||
|
|
1c40685d32 | ||
|
|
31c6e7af6a | ||
|
|
552ba67bb1 | ||
|
|
651254dcc7 | ||
|
|
26bdafcbf9 | ||
|
|
02dc9e788f | ||
|
|
e11c6e9961 | ||
|
|
e4eaa92728 | ||
|
|
577f8e5ac6 | ||
|
|
95ba6cdd54 | ||
|
|
7ce6cb9ab4 | ||
|
|
8723cade21 | ||
|
|
d956d9db47 | ||
|
|
ecf93ac986 | ||
|
|
b3a01be2f3 | ||
|
|
00045a3009 | ||
|
|
3f7188dd94 | ||
|
|
720218fea1 | ||
|
|
73aa95592f | ||
|
|
ad3fdbc0a4 | ||
|
|
73cbd21b5e | ||
|
|
c5ba0c2f54 | ||
|
|
edddf394b8 | ||
|
|
61d259f950 | ||
|
|
c01735865f | ||
|
|
ca46c5dbe2 | ||
|
|
2da127abb5 | ||
|
|
bc33f2200d | ||
|
|
fd399cde00 | ||
|
|
00c74019f4 | ||
|
|
9d0063befa | ||
|
|
01e55ebb26 | ||
|
|
4bbad1dac7 | ||
|
|
ddbda328b3 | ||
|
|
8ffbeeda80 | ||
|
|
1d1ffaf912 | ||
|
|
e0cff02061 | ||
|
|
7fe95bb0d5 |
@@ -103,7 +103,7 @@ if test ! -z $SDK32; then
|
|||||||
ln -fs ${FRAMEWORK_VERSION}/Resources Resources
|
ln -fs ${FRAMEWORK_VERSION}/Resources Resources
|
||||||
ln -fs ${FRAMEWORK_VERSION}/Headers Headers
|
ln -fs ${FRAMEWORK_VERSION}/Headers Headers
|
||||||
cd Versions
|
cd Versions
|
||||||
ln -fs ${FRAMEWORK_VERSION} Current
|
ln -fs $(basename "${FRAMEWORK_VERSION}") Current
|
||||||
|
|
||||||
echo Testing for SDK64
|
echo Testing for SDK64
|
||||||
if test -d $SDK64_DIR; then
|
if test -d $SDK64_DIR; then
|
||||||
|
|||||||
189
RELEASE-NOTES
189
RELEASE-NOTES
@@ -1,6 +1,6 @@
|
|||||||
Curl and libcurl 7.30.0
|
Curl and libcurl 7.31.0
|
||||||
|
|
||||||
Public curl releases: 132
|
Public curl releases: 133
|
||||||
Command line options: 152
|
Command line options: 152
|
||||||
curl_easy_setopt() options: 199
|
curl_easy_setopt() options: 199
|
||||||
Public functions in libcurl: 58
|
Public functions in libcurl: 58
|
||||||
@@ -14,75 +14,58 @@ Curl and libcurl 7.30.0
|
|||||||
|
|
||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o imap: Changed response tag generation to be completely unique
|
o darwinssl: add TLS session resumption
|
||||||
o imap: Added support for SASL-IR extension
|
o darwinssl: add TLS crypto authentication
|
||||||
o imap: Added support for the list command
|
o imap/pop3/smtp: Added support for ;auth=<mech> in the URL
|
||||||
o imap: Added support for the append command
|
o imap/pop3/smtp: Added support for ;auth=<mech> to CURLOPT_USERPWD
|
||||||
o imap: Added custom request parsing
|
o usercertinmem.c: add example showing user cert in memory
|
||||||
o imap: Added support to the fetch command for UID and SECTION properties
|
o url: Added smtp and pop3 hostnames to the protocol detection list
|
||||||
o imap: Added parsing and verification of the UIDVALIDITY mailbox attribute
|
o imap/pop3/smtp: Added support for enabling the SASL initial response [8]
|
||||||
o darwinssl: Make certificate errors less techy
|
o curl -E: allow to use ':' in certificate nicknames [10]
|
||||||
o imap/pop3/smtp: Added support for the STARTTLS capability
|
|
||||||
o checksrc: ban use of sprintf, vsprintf, strcat, strncat and gets
|
|
||||||
o curl_global_init() now accepts the CURL_GLOBAL_ACK_EINTR flag [10]
|
|
||||||
o Added CURLMOPT_MAX_HOST_CONNECTIONS, CURLMOPT_MAX_TOTAL_CONNECTIONS for
|
|
||||||
new multi interface connection handling
|
|
||||||
o Added CURLMOPT_MAX_PIPELINE_LENGTH, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE,
|
|
||||||
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLMOPT_PIPELINING_SITE_BL and
|
|
||||||
CURLMOPT_PIPELINING_SERVER_BL for new pipelining control [15]
|
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
o SECURITY ADVISORY: cookie tailmatching to avoid cross-domain leakage [25]
|
o SECURITY VULNERABILITY: curl_easy_unescape() may parse data beyond the end
|
||||||
o darwinssl: Fix build under Leopard
|
of the input buffer [26]
|
||||||
o DONE: consider callback-aborted transfers premature [1]
|
|
||||||
o ntlm: Fixed memory leaks
|
o FTP: access files in root dir correctly [1]
|
||||||
o smtp: Fixed an issue when processing EHLO failure responses
|
o configure: try pthread_create without -lpthread [2]
|
||||||
o pop3: Fixed incorrect return value from pop3_endofresp()
|
o FTP: handle a 230 welcome response [3]
|
||||||
o pop3: Fixed SASL authentication capability detection
|
o curl-config: don't output static libs when they are disabled
|
||||||
o pop3: Fixed blocking SSL connect when connecting via POP3S
|
o CURL_CHECK_CA_BUNDLE: don't check for paths when cross-compiling [4]
|
||||||
o imap: Fixed memory leak when performing multiple selects
|
o Various documentation updates
|
||||||
o nss: fix misplaced code enabling non-blocking socket mode
|
o getinfo.c: reset timecond when clearing session-info variables [5]
|
||||||
o AddFormData: prevent only directories from being posted [2]
|
o FILE: prevent an artificial timeout event due to stale speed-check data [6]
|
||||||
o darwinssl: fix infinite loop if server disconnected abruptly [3]
|
o ftp_state_pasv_resp: connect through proxy also when set by env [7]
|
||||||
o metalink: fix improbable crash parsing metalink filename
|
o sshserver: disable StrictHostKeyChecking
|
||||||
o show proper host name on failed resolve
|
o ftpserver: Fixed imap logout confirmation data
|
||||||
o MacOSX-Framework: Make script work in Xcode 4.0 and later
|
o curl_easy_init: use less mallocs
|
||||||
o strlcat: remove function [4]
|
o smtp: Fixed unknown percentage complete in progress bar
|
||||||
o darwinssl: Fix send glitchiness with data > 32 or so KB [5]
|
o smtp: Fixed sending of double CRLF caused by first in EOB
|
||||||
o polarssl: better 1.1.x and 1.2.x support
|
o bindlocal: move brace out of #ifdef [9]
|
||||||
o various documentation improvements
|
o winssl: Fixed invalid memory access during SSL shutdown [11]
|
||||||
o multi: NULL pointer reference when closing an unused multi handle [9]
|
o OS X framework: fix invalid symbolic link
|
||||||
o SOCKS: fix socks proxy when noproxy matched [7]
|
o OpenSSL: allow empty server certificate subject [12]
|
||||||
o install-sh: updated to support multiple source files as arguments [6]
|
o axtls: prevent memleaks on SSL handshake failures
|
||||||
o PolarSSL: added human readable error strings
|
o cookies: only consider full path matches
|
||||||
o resolver_error: remove wrong error message output
|
o Revert win32 MemoryTracking: wcsdup() _wcsdup() and _tcsdup() [13]
|
||||||
o docs: updates HTML index and general improvements
|
o Curl_cookie_add: handle IPv6 hosts [14]
|
||||||
o curlbuild.h.dist: enhance non-configure GCC ABI detection logic
|
o ossl_send: SSL_write() returning 0 is an error too
|
||||||
o sasl: Fixed null pointer reference when decoding empty digest challenge [8]
|
o ossl_recv: SSL_read() returning 0 is an error too
|
||||||
o easy: do not ignore poll() failures other than EINTR
|
o Digest auth: escape user names with \ or " in them [15]
|
||||||
o darwinssl: disable ECC ciphers under Mountain Lion by default
|
o curl_formadd.3: fixed wrong "end-marker" syntax [16]
|
||||||
o CONNECT: count received headers [11]
|
o libcurl-tutorial.3: fix incorrect backslash [17]
|
||||||
o build: fixes for VMS
|
o curl_multi_wait: reduce timeout if the multi handle wants to [18]
|
||||||
o CONNECT: clear 'rewindaftersend' on success [12]
|
o tests/Makefile: typo in the perlcheck target [19]
|
||||||
o HTTP proxy: insert slash in URL if missing [13]
|
o axtls: honor disabled VERIFYHOST
|
||||||
o hiperfifo: updated to use current libevent API [14]
|
o OpenSSL: avoid double free in the PKCS12 certificate code [20]
|
||||||
o getinmemory.c: abort the transfer nicely if not enough memory
|
o multi_socket: reduce timeout inaccuracy margin [21]
|
||||||
o improved win32 memorytracking
|
o digest: support auth-int for empty entity body [22]
|
||||||
o corrected proxy header response headers count [16]
|
o axtls: now done non-blocking
|
||||||
o FTP quote operations on re-used connection [17]
|
o lib1900: use tutil_tvnow instead of gettimeofday
|
||||||
o tcpkeepalive on win32 [18]
|
o curl_easy_perform: avoid busy-looping [23]
|
||||||
o tcpkeepalive on Mac OS X [23]
|
o CURLOPT_COOKIELIST: take cookie share lock [24]
|
||||||
o easy: acknowledge the CURLOPT_MAXCONNECTS option properly [19]
|
o multi_socket: react on socket close immediately [25]
|
||||||
o easy interface: restore default MAXCONNECTS to 5
|
|
||||||
o win32: don't set SO_SNDBUF for windows vista or later versions [20]
|
|
||||||
o HTTP: made cookie sort function more deterministic
|
|
||||||
o winssl: Fixed memory leak if connection was not successful
|
|
||||||
o FTP: wait on both connections during active STOR state [21]
|
|
||||||
o connect: treat a failed local bind of an interface as a non-fatal error [22]
|
|
||||||
o darwinssl: disable insecure ciphers by default
|
|
||||||
o FTP: handle "rubbish" in front of directory name in 257 responses [24]
|
|
||||||
o mk-ca-bundle: Fixed lost OpenSSL output with "-t"
|
|
||||||
|
|
||||||
This release includes the following known bugs:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
@@ -91,43 +74,43 @@ This release includes the following known bugs:
|
|||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Kamil Dudka, Steve Holme, Nick Zitzmann, Patricia Muscalu, Dan Fandrich,
|
David Strauss, Kamil Dudka, Steve Holme, Nick Zitzmann, Sam Deane, Duncan,
|
||||||
Gisle Vanem, Guenter Knauf, Yang Tse, Oliver Gondža, Aki Koskinen,
|
Anders Havn, Dan Fandrich, Paul Howarth, Dave Reisner, Wouter Van Rooy,
|
||||||
Alexander Klauer, Kim Vandry, Willem Sparreboom, Jeremy Huddleston,
|
Linus Nielsen Feltzing, Ishan SinghLevett, Alessandro Ghedini,
|
||||||
Bruno de Carvalho, Rainer Jung, Jeremy Huddleston, Kim Vandry, Jiri Hruska,
|
Ludovico Cavedon, Zdenek Pavlas, Zekun Ni, Lars Johannesen, Marc Hoersken,
|
||||||
Alexander Klauer, Saran Neti, Alessandro Ghedini, Linus Nielsen Feltzing,
|
Renaud Guillard, John Gardiner Myers, Jared Jennings, Eric Hu,
|
||||||
Martin Jansen, John E. Malmberg, Tom Grace, Patrick Monnerat,
|
Yamada Yasuharu, Stefan Neis, Mike Giancola, Eric S. Raymond, Andrii Moiseiev,
|
||||||
Zdenek Pavlas, Myk Taylor, Cédric Deltheil, Robert Wruck, Sam Deane,
|
Christian Weisgerber, Peter Gal, Aleksey Tulinov, Hang Su, Sergei Nikulov,
|
||||||
Clemens Gruber, Marc Hoersken, Tomas Mlcoch, Fredrik Thulin, Steven Gu,
|
Miguel Angel, Nach M. S., Benjamin Gilbert, Erik Johansson, Timo Sirainen,
|
||||||
Andrew Kurushin, Christian Hägele, Daniel Theron, Bill Middlecamp,
|
Guenter Knauf
|
||||||
Richard Michael, Yamada Yasuharu
|
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
|
||||||
References to bug reports and discussions on issues:
|
References to bug reports and discussions on issues:
|
||||||
|
|
||||||
[1] = http://curl.haxx.se/bug/view.cgi?id=1184
|
[1] = http://curl.haxx.se/mail/lib-2013-04/0142.html
|
||||||
[2] = http://curl.haxx.se/mail/archive-2013-02/0040.html
|
[2] = http://curl.haxx.se/bug/view.cgi?id=1216
|
||||||
[3] = http://curl.haxx.se/mail/lib-2013-03/0014.html
|
[3] = http://curl.haxx.se/mail/lib-2013-02/0102.html
|
||||||
[4] = http://curl.haxx.se/bug/view.cgi?id=1192
|
[4] = http://curl.haxx.se/mail/lib-2013-04/0294.html
|
||||||
[5] = http://curl.haxx.se/mail/lib-2013-02/0145.html
|
[5] = http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=705783
|
||||||
[6] = http://curl.haxx.se/bug/view.cgi?id=1195
|
[6] = https://bugzilla.redhat.com/906031
|
||||||
[7] = http://curl.haxx.se/bug/view.cgi?id=1190
|
[7] = http://curl.haxx.se/bug/view.cgi?id=1218
|
||||||
[8] = http://curl.haxx.se/bug/view.cgi?id=1193
|
[8] = http://curl.haxx.se/mail/lib-2012-03/0114.html
|
||||||
[9] = http://curl.haxx.se/bug/view.cgi?id=1194
|
[9] = http://curl.haxx.se/mail/lib-2013-05/0000.html
|
||||||
[10] = http://curl.haxx.se/bug/view.cgi?id=1168
|
[10] = http://curl.haxx.se/bug/view.cgi?id=1196
|
||||||
[11] = http://curl.haxx.se/bug/view.cgi?id=1204
|
[11] = http://curl.haxx.se/bug/view.cgi?id=1219
|
||||||
[12] = https://groups.google.com/d/msg/msysgit/B31LNftR4BI/KhRTz0iuGmUJ
|
[12] = http://curl.haxx.se/bug/view.cgi?id=1220
|
||||||
[13] = http://curl.haxx.se/bug/view.cgi?id=1206
|
[13] = http://curl.haxx.se/mail/lib-2013-05/0070.html
|
||||||
[14] = http://curl.haxx.se/bug/view.cgi?id=1199
|
[14] = http://curl.haxx.se/bug/view.cgi?id=1221
|
||||||
[15] = http://daniel.haxx.se/blog/2013/03/26/better-pipelining-in-libcurl-7-30-0/
|
[15] = http://curl.haxx.se/bug/view.cgi?id=1230
|
||||||
[16] = http://curl.haxx.se/bug/view.cgi?id=1204
|
[16] = http://curl.haxx.se/bug/view.cgi?id=1233
|
||||||
[17] = http://curl.haxx.se/mail/lib-2013-03/0319.html
|
[17] = http://curl.haxx.se/bug/view.cgi?id=1234
|
||||||
[18] = http://curl.haxx.se/bug/view.cgi?id=1209
|
[18] = http://curl.haxx.se/bug/view.cgi?id=1224
|
||||||
[19] = http://curl.haxx.se/bug/view.cgi?id=1212
|
[19] = http://curl.haxx.se/bug/view.cgi?id=1239
|
||||||
[20] = http://curl.haxx.se/bug/view.cgi?id=1188
|
[20] = http://curl.haxx.se/bug/view.cgi?id=1236
|
||||||
[21] = http://curl.haxx.se/bug/view.cgi?id=1183
|
[21] = http://curl.haxx.se/bug/view.cgi?id=1228
|
||||||
[22] = http://curl.haxx.se/bug/view.cgi?id=1189
|
[22] = http://curl.haxx.se/bug/view.cgi?id=1235
|
||||||
[23] = http://curl.haxx.se/bug/view.cgi?id=1214
|
[23] = http://curl.haxx.se/bug/view.cgi?id=1238
|
||||||
[24] = http://curl.haxx.se/mail/lib-2013-04/0113.html
|
[24] = http://curl.haxx.se/bug/view.cgi?id=1215
|
||||||
[25] = http://curl.haxx.se/docs/adv_20130412.html
|
[25] = http://curl.haxx.se/bug/view.cgi?id=1248
|
||||||
|
[26] = http://curl.haxx.se/docs/adv_20130622.html
|
||||||
|
|||||||
11
acinclude.m4
11
acinclude.m4
@@ -2619,8 +2619,10 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
|||||||
fi
|
fi
|
||||||
capath="$want_capath"
|
capath="$want_capath"
|
||||||
ca="no"
|
ca="no"
|
||||||
else
|
elif test "x$cross_compiling" != "xyes"; then
|
||||||
dnl neither of --with-ca-* given
|
dnl NOT cross-compiling and...
|
||||||
|
dnl neither of the --with-ca-* options are provided
|
||||||
|
|
||||||
dnl first try autodetecting a CA bundle , then a CA path
|
dnl first try autodetecting a CA bundle , then a CA path
|
||||||
dnl both autodetections can be skipped by --without-ca-*
|
dnl both autodetections can be skipped by --without-ca-*
|
||||||
ca="no"
|
ca="no"
|
||||||
@@ -2656,10 +2658,11 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
dnl no option given and cross-compiling
|
||||||
|
AC_MSG_WARN([skipped the ca-cert path detection when cross-compiling])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if test "x$ca" != "xno"; then
|
if test "x$ca" != "xno"; then
|
||||||
CURL_CA_BUNDLE='"'$ca'"'
|
CURL_CA_BUNDLE='"'$ca'"'
|
||||||
AC_DEFINE_UNQUOTED(CURL_CA_BUNDLE, "$ca", [Location of default ca bundle])
|
AC_DEFINE_UNQUOTED(CURL_CA_BUNDLE, "$ca", [Location of default ca bundle])
|
||||||
|
|||||||
27
configure.ac
27
configure.ac
@@ -3158,14 +3158,26 @@ if test "$want_thres" = "yes"; then
|
|||||||
AC_CHECK_HEADER(pthread.h,
|
AC_CHECK_HEADER(pthread.h,
|
||||||
[ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>])
|
[ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>])
|
||||||
save_CFLAGS="$CFLAGS"
|
save_CFLAGS="$CFLAGS"
|
||||||
|
|
||||||
|
dnl first check for function without lib
|
||||||
|
AC_CHECK_FUNC(pthread_create, [USE_THREADS_POSIX=1] )
|
||||||
|
|
||||||
|
dnl if it wasn't found without lib, search for it in pthread lib
|
||||||
|
if test "$USE_THREADS_POSIX" != "1"
|
||||||
|
then
|
||||||
CFLAGS="$CFLAGS -pthread"
|
CFLAGS="$CFLAGS -pthread"
|
||||||
AC_CHECK_LIB(pthread, pthread_create,
|
AC_CHECK_LIB(pthread, pthread_create,
|
||||||
[ AC_MSG_NOTICE([using POSIX threaded DNS lookup])
|
[USE_THREADS_POSIX=1],
|
||||||
AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup])
|
|
||||||
USE_THREADS_POSIX=1
|
|
||||||
curl_res_msg="threaded"
|
|
||||||
],
|
|
||||||
[ CFLAGS="$save_CFLAGS"])
|
[ CFLAGS="$save_CFLAGS"])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$USE_THREADS_POSIX" = "x1"
|
||||||
|
then
|
||||||
|
AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup])
|
||||||
|
curl_res_msg="POSIX threaded"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -3338,6 +3350,11 @@ dnl yes or no
|
|||||||
ENABLE_SHARED="$enable_shared"
|
ENABLE_SHARED="$enable_shared"
|
||||||
AC_SUBST(ENABLE_SHARED)
|
AC_SUBST(ENABLE_SHARED)
|
||||||
|
|
||||||
|
dnl to let curl-config output the static libraries correctly
|
||||||
|
ENABLE_STATIC="$enable_static"
|
||||||
|
AC_SUBST(ENABLE_STATIC)
|
||||||
|
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl For keeping supported features and protocols also in pkg-config file
|
dnl For keeping supported features and protocols also in pkg-config file
|
||||||
dnl since it is more cross-compile friendly than curl-config
|
dnl since it is more cross-compile friendly than curl-config
|
||||||
|
|||||||
@@ -155,7 +155,12 @@ while test $# -gt 0; do
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
--static-libs)
|
--static-libs)
|
||||||
|
if test "X@ENABLE_STATIC@" != "Xno" ; then
|
||||||
echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
|
echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@
|
||||||
|
else
|
||||||
|
echo "curl was built with static libraries disabled" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
--configure)
|
--configure)
|
||||||
|
|||||||
16
docs/FAQ
16
docs/FAQ
@@ -728,7 +728,7 @@ FAQ
|
|||||||
When passing on a URL to curl to use, it may respond that the particular
|
When passing on a URL to curl to use, it may respond that the particular
|
||||||
protocol is not supported or disabled. The particular way this error message
|
protocol is not supported or disabled. The particular way this error message
|
||||||
is phrased is because curl doesn't make a distinction internally of whether
|
is phrased is because curl doesn't make a distinction internally of whether
|
||||||
a particular protocol is not supported (ie never got any code added that
|
a particular protocol is not supported (i.e. never got any code added that
|
||||||
knows how to speak that protocol) or if it was explicitly disabled. curl can
|
knows how to speak that protocol) or if it was explicitly disabled. curl can
|
||||||
be built to only support a given set of protocols, and the rest would then
|
be built to only support a given set of protocols, and the rest would then
|
||||||
be disabled or not supported.
|
be disabled or not supported.
|
||||||
@@ -1055,11 +1055,11 @@ FAQ
|
|||||||
|
|
||||||
4.19 Why doesn't cURL return an error when the network cable is unplugged?
|
4.19 Why doesn't cURL return an error when the network cable is unplugged?
|
||||||
|
|
||||||
Unplugging the cable is not an error situation. The TCP/IP protocol stack
|
Unplugging a cable is not an error situation. The TCP/IP protocol stack
|
||||||
was designed to be fault tolerant, so even though there may be a physical
|
was designed to be fault tolerant, so even though there may be a physical
|
||||||
break somewhere the connection shouldn't be affected, just possibly
|
break somewhere the connection shouldn't be affected, just possibly
|
||||||
delayed. Eventually, the physical break will be fixed or the data will be
|
delayed. Eventually, the physical break will be fixed or the data will be
|
||||||
re-routed around the physical problem.
|
re-routed around the physical problem through another path.
|
||||||
|
|
||||||
In such cases, the TCP/IP stack is responsible for detecting when the
|
In such cases, the TCP/IP stack is responsible for detecting when the
|
||||||
network connection is irrevocably lost. Since with some protocols it is
|
network connection is irrevocably lost. Since with some protocols it is
|
||||||
@@ -1077,6 +1077,12 @@ FAQ
|
|||||||
falls too low, and --connect-timeout and --max-time can be used to put an
|
falls too low, and --connect-timeout and --max-time can be used to put an
|
||||||
overall timeout on the connection phase or the entire transfer.
|
overall timeout on the connection phase or the entire transfer.
|
||||||
|
|
||||||
|
A libcurl-using application running in a known physical environment (e.g.
|
||||||
|
an embedded device with only a single network connection) may want to act
|
||||||
|
immediately if its lone network connection goes down. That can be achieved
|
||||||
|
by having the application monitor the network connection on its own using an
|
||||||
|
OS-specific mechanism, then signalling libcurl to abort (see also item 5.13).
|
||||||
|
|
||||||
|
|
||||||
5. libcurl Issues
|
5. libcurl Issues
|
||||||
|
|
||||||
@@ -1086,7 +1092,9 @@ FAQ
|
|||||||
|
|
||||||
We have written the libcurl code specifically adjusted for multi-threaded
|
We have written the libcurl code specifically adjusted for multi-threaded
|
||||||
programs. libcurl will use thread-safe functions instead of non-safe ones if
|
programs. libcurl will use thread-safe functions instead of non-safe ones if
|
||||||
your system has such.
|
your system has such. Note that you must never share the same handle in
|
||||||
|
multiple threads.
|
||||||
|
|
||||||
|
|
||||||
If you use a OpenSSL-powered libcurl in a multi-threaded environment, you
|
If you use a OpenSSL-powered libcurl in a multi-threaded environment, you
|
||||||
need to provide one or two locking functions:
|
need to provide one or two locking functions:
|
||||||
|
|||||||
14
docs/HISTORY
14
docs/HISTORY
@@ -7,19 +7,19 @@
|
|||||||
How cURL Became Like This
|
How cURL Became Like This
|
||||||
|
|
||||||
|
|
||||||
In the second half of 1997, Daniel Stenberg came up with the idea to make
|
Towards the end of 1996, Daniel Stenberg came up with the idea to make
|
||||||
currency-exchange calculations available to Internet Relay Chat (IRC)
|
currency-exchange calculations available to Internet Relay Chat (IRC)
|
||||||
users. All the necessary data are published on the Web; he just needed to
|
users. All the necessary data are published on the Web; he just needed to
|
||||||
automate their retrieval.
|
automate their retrieval.
|
||||||
|
|
||||||
Daniel simply adopted an existing command-line open-source tool, httpget, that
|
Daniel simply adopted an existing command-line open-source tool, httpget, that
|
||||||
Brazilian Rafael Sagula had written. After a few minor adjustments, it did
|
Brazilian Rafael Sagula had written and recently release version 0.1 of. After
|
||||||
just what he needed.
|
a few minor adjustments, it did just what he needed. HttpGet 1.0 was released
|
||||||
|
on April 8th 1997 with brand new HTTP proxy support.
|
||||||
|
|
||||||
Soon, he found currencies on a GOPHER site, so support for that had to go in,
|
We soon found and fixed support for getting currencies over GOPHER. Once FTP
|
||||||
and not before long FTP download support was added as well. The name of the
|
download support was added, the name of the project was changed and urlget 2.0
|
||||||
project was changed to urlget to better fit what it actually did now, since
|
was released in August 1997. The http-only days were already passed.
|
||||||
the http-only days were already passed.
|
|
||||||
|
|
||||||
The project slowly grew bigger. When upload capabilities were added and the
|
The project slowly grew bigger. When upload capabilities were added and the
|
||||||
name once again was misleading, a second name change was made and on March 20,
|
name once again was misleading, a second name change was made and on March 20,
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ Win32
|
|||||||
adjust as necessary. It is also possible to override these paths with
|
adjust as necessary. It is also possible to override these paths with
|
||||||
environment variables, for example:
|
environment variables, for example:
|
||||||
|
|
||||||
set ZLIB_PATH=c:\zlib-1.2.7
|
set ZLIB_PATH=c:\zlib-1.2.8
|
||||||
set OPENSSL_PATH=c:\openssl-0.9.8y
|
set OPENSSL_PATH=c:\openssl-0.9.8y
|
||||||
set LIBSSH2_PATH=c:\libssh2-1.4.3
|
set LIBSSH2_PATH=c:\libssh2-1.4.3
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ Win32
|
|||||||
documentation on how to compile zlib. Define the ZLIB_PATH environment
|
documentation on how to compile zlib. Define the ZLIB_PATH environment
|
||||||
variable to the location of zlib.h and zlib.lib, for example:
|
variable to the location of zlib.h and zlib.lib, for example:
|
||||||
|
|
||||||
set ZLIB_PATH=c:\zlib-1.2.7
|
set ZLIB_PATH=c:\zlib-1.2.8
|
||||||
|
|
||||||
Then run 'nmake vc-zlib' in curl's root directory.
|
Then run 'nmake vc-zlib' in curl's root directory.
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,17 @@ join in and help us correct one or more of these! Also be sure to check the
|
|||||||
changelog of the current development status, as one or more of these problems
|
changelog of the current development status, as one or more of these problems
|
||||||
may have been fixed since this was written!
|
may have been fixed since this was written!
|
||||||
|
|
||||||
|
82. When building with the Windows Borland compiler, it fails because the
|
||||||
|
"tlib" tool doesn't support hyphens (minus signs) in file names and we have
|
||||||
|
such in the build.
|
||||||
|
http://curl.haxx.se/bug/view.cgi?id=1222
|
||||||
|
|
||||||
|
81. When using -J (with -O), automaticly resumed downloading together with "-C
|
||||||
|
-" fails. Without -J the same command line works! This happens because the
|
||||||
|
resume logic is worked out before the target file name (and thus its
|
||||||
|
pre-transfer size) has been figured out!
|
||||||
|
http://curl.haxx.se/bug/view.cgi?id=1169
|
||||||
|
|
||||||
80. Curl doesn't recognize certificates in DER format in keychain, but it
|
80. Curl doesn't recognize certificates in DER format in keychain, but it
|
||||||
works with PEM.
|
works with PEM.
|
||||||
http://curl.haxx.se/bug/view.cgi?id=3439999
|
http://curl.haxx.se/bug/view.cgi?id=3439999
|
||||||
|
|||||||
28
docs/THANKS
28
docs/THANKS
@@ -13,9 +13,9 @@ Adam Tkac
|
|||||||
Adrian Schuur
|
Adrian Schuur
|
||||||
Adriano Meirelles
|
Adriano Meirelles
|
||||||
Ajit Dhumale
|
Ajit Dhumale
|
||||||
|
Aki Koskinen
|
||||||
Akos Pasztory
|
Akos Pasztory
|
||||||
Alan Pinstein
|
Alan Pinstein
|
||||||
Albert Chin
|
|
||||||
Albert Chin-A-Young
|
Albert Chin-A-Young
|
||||||
Albert Choy
|
Albert Choy
|
||||||
Ale Vesely
|
Ale Vesely
|
||||||
@@ -31,6 +31,7 @@ Alex Suykov
|
|||||||
Alex Vinnik
|
Alex Vinnik
|
||||||
Alex aka WindEagle
|
Alex aka WindEagle
|
||||||
Alexander Beedie
|
Alexander Beedie
|
||||||
|
Alexander Klauer
|
||||||
Alexander Kourakos
|
Alexander Kourakos
|
||||||
Alexander Krasnostavsky
|
Alexander Krasnostavsky
|
||||||
Alexander Lazic
|
Alexander Lazic
|
||||||
@@ -64,6 +65,7 @@ Andrew Biggs
|
|||||||
Andrew Bushnell
|
Andrew Bushnell
|
||||||
Andrew Francis
|
Andrew Francis
|
||||||
Andrew Fuller
|
Andrew Fuller
|
||||||
|
Andrew Kurushin
|
||||||
Andrew Moise
|
Andrew Moise
|
||||||
Andrew Wansink
|
Andrew Wansink
|
||||||
Andrew de los Reyes
|
Andrew de los Reyes
|
||||||
@@ -107,6 +109,7 @@ Bernhard Reutner-Fischer
|
|||||||
Bertrand Demiddelaer
|
Bertrand Demiddelaer
|
||||||
Bill Egert
|
Bill Egert
|
||||||
Bill Hoffman
|
Bill Hoffman
|
||||||
|
Bill Middlecamp
|
||||||
Bjoern Sikora
|
Bjoern Sikora
|
||||||
Bjorn Augustsson
|
Bjorn Augustsson
|
||||||
Bjorn Reese
|
Bjorn Reese
|
||||||
@@ -153,7 +156,6 @@ Chris Maltby
|
|||||||
Chris Mumford
|
Chris Mumford
|
||||||
Chris Smowton
|
Chris Smowton
|
||||||
Christian Grothoff
|
Christian Grothoff
|
||||||
Christian Hagele
|
|
||||||
Christian Hägele
|
Christian Hägele
|
||||||
Christian Krause
|
Christian Krause
|
||||||
Christian Kurz
|
Christian Kurz
|
||||||
@@ -169,6 +171,7 @@ Christopher Stone
|
|||||||
Ciprian Badescu
|
Ciprian Badescu
|
||||||
Claes Jakobsson
|
Claes Jakobsson
|
||||||
Clarence Gardner
|
Clarence Gardner
|
||||||
|
Clemens Gruber
|
||||||
Clifford Wolf
|
Clifford Wolf
|
||||||
Cody Jones
|
Cody Jones
|
||||||
Colin Hogben
|
Colin Hogben
|
||||||
@@ -180,10 +183,10 @@ Craig A West
|
|||||||
Craig Davison
|
Craig Davison
|
||||||
Craig Markwardt
|
Craig Markwardt
|
||||||
Cris Bailiff
|
Cris Bailiff
|
||||||
Cristian Rodriguez
|
|
||||||
Cristian Rodríguez
|
Cristian Rodríguez
|
||||||
Curt Bogmine
|
Curt Bogmine
|
||||||
Cyrill Osterwalder
|
Cyrill Osterwalder
|
||||||
|
Cédric Deltheil
|
||||||
Dag Ekengren
|
Dag Ekengren
|
||||||
Dagobert Michelsen
|
Dagobert Michelsen
|
||||||
Damien Adant
|
Damien Adant
|
||||||
@@ -317,6 +320,7 @@ Fred Machado
|
|||||||
Fred New
|
Fred New
|
||||||
Fred Noz
|
Fred Noz
|
||||||
Frederic Lepied
|
Frederic Lepied
|
||||||
|
Fredrik Thulin
|
||||||
Gabriel Kuri
|
Gabriel Kuri
|
||||||
Gabriel Sjoberg
|
Gabriel Sjoberg
|
||||||
Garrett Holmstrom
|
Garrett Holmstrom
|
||||||
@@ -438,6 +442,7 @@ Jeff Pohlmeyer
|
|||||||
Jeff Weber
|
Jeff Weber
|
||||||
Jeffrey Pohlmeyer
|
Jeffrey Pohlmeyer
|
||||||
Jeremy Friesner
|
Jeremy Friesner
|
||||||
|
Jeremy Huddleston
|
||||||
Jerome Muffat-Meridol
|
Jerome Muffat-Meridol
|
||||||
Jerome Vouillon
|
Jerome Vouillon
|
||||||
Jerry Wu
|
Jerry Wu
|
||||||
@@ -449,8 +454,8 @@ Jim Drash
|
|||||||
Jim Freeman
|
Jim Freeman
|
||||||
Jim Hollinger
|
Jim Hollinger
|
||||||
Jim Meyering
|
Jim Meyering
|
||||||
Jiri Jaburek
|
|
||||||
Jiri Hruska
|
Jiri Hruska
|
||||||
|
Jiri Jaburek
|
||||||
Jocelyn Jaubert
|
Jocelyn Jaubert
|
||||||
Joe Halpin
|
Joe Halpin
|
||||||
Joe Malicki
|
Joe Malicki
|
||||||
@@ -534,6 +539,7 @@ Kevin Lussier
|
|||||||
Kevin Reed
|
Kevin Reed
|
||||||
Kevin Roth
|
Kevin Roth
|
||||||
Kim Rinnewitz
|
Kim Rinnewitz
|
||||||
|
Kim Vandry
|
||||||
Kimmo Kinnunen
|
Kimmo Kinnunen
|
||||||
Kjell Ericson
|
Kjell Ericson
|
||||||
Kjetil Jacobsen
|
Kjetil Jacobsen
|
||||||
@@ -614,6 +620,7 @@ Martin C. Martin
|
|||||||
Martin Drasar
|
Martin Drasar
|
||||||
Martin Hager
|
Martin Hager
|
||||||
Martin Hedenfalk
|
Martin Hedenfalk
|
||||||
|
Martin Jansen
|
||||||
Martin Lemke
|
Martin Lemke
|
||||||
Martin Skinner
|
Martin Skinner
|
||||||
Martin Storsjo
|
Martin Storsjo
|
||||||
@@ -676,6 +683,7 @@ Mitz Wark
|
|||||||
Mohamed Lrhazi
|
Mohamed Lrhazi
|
||||||
Mohun Biswas
|
Mohun Biswas
|
||||||
Moonesamy
|
Moonesamy
|
||||||
|
Myk Taylor
|
||||||
Nathan Coulter
|
Nathan Coulter
|
||||||
Nathan O'Sullivan
|
Nathan O'Sullivan
|
||||||
Nathanael Nerode
|
Nathanael Nerode
|
||||||
@@ -709,6 +717,7 @@ Ofer
|
|||||||
Olaf Flebbe
|
Olaf Flebbe
|
||||||
Olaf Stueben
|
Olaf Stueben
|
||||||
Olaf Stüben
|
Olaf Stüben
|
||||||
|
Oliver Gondža
|
||||||
Olivier Berger
|
Olivier Berger
|
||||||
Oren Tirosh
|
Oren Tirosh
|
||||||
Ori Avtalion
|
Ori Avtalion
|
||||||
@@ -720,6 +729,7 @@ Pascal Terjan
|
|||||||
Pasha Kuznetsov
|
Pasha Kuznetsov
|
||||||
Pat Ray
|
Pat Ray
|
||||||
Patrice Guerin
|
Patrice Guerin
|
||||||
|
Patricia Muscalu
|
||||||
Patrick Bihan-Faou
|
Patrick Bihan-Faou
|
||||||
Patrick Monnerat
|
Patrick Monnerat
|
||||||
Patrick Scott
|
Patrick Scott
|
||||||
@@ -779,6 +789,7 @@ Quinn Slack
|
|||||||
Rafa Muyo
|
Rafa Muyo
|
||||||
Rafael Sagula
|
Rafael Sagula
|
||||||
Rainer Canavan
|
Rainer Canavan
|
||||||
|
Rainer Jung
|
||||||
Rainer Koenig
|
Rainer Koenig
|
||||||
Rajesh Naganathan
|
Rajesh Naganathan
|
||||||
Ralf S. Engelschall
|
Ralf S. Engelschall
|
||||||
@@ -806,6 +817,7 @@ Richard Bramante
|
|||||||
Richard Clayton
|
Richard Clayton
|
||||||
Richard Cooper
|
Richard Cooper
|
||||||
Richard Gorton
|
Richard Gorton
|
||||||
|
Richard Michael
|
||||||
Richard Prescott
|
Richard Prescott
|
||||||
Richard Silverman
|
Richard Silverman
|
||||||
Rick Jones
|
Rick Jones
|
||||||
@@ -822,6 +834,7 @@ Robert Iakobashvili
|
|||||||
Robert Olson
|
Robert Olson
|
||||||
Robert Schumann
|
Robert Schumann
|
||||||
Robert Weaver
|
Robert Weaver
|
||||||
|
Robert Wruck
|
||||||
Robin Cornelius
|
Robin Cornelius
|
||||||
Robin Johnson
|
Robin Johnson
|
||||||
Robin Kay
|
Robin Kay
|
||||||
@@ -846,6 +859,7 @@ Ryan Schmidt
|
|||||||
S. Moonesamy
|
S. Moonesamy
|
||||||
Salvador Dávila
|
Salvador Dávila
|
||||||
Salvatore Sorrentino
|
Salvatore Sorrentino
|
||||||
|
Sam Deane
|
||||||
Sam Listopad
|
Sam Listopad
|
||||||
Sampo Kellomaki
|
Sampo Kellomaki
|
||||||
Samuel Díaz García
|
Samuel Díaz García
|
||||||
@@ -856,6 +870,7 @@ Sandor Feldi
|
|||||||
Santhana Todatry
|
Santhana Todatry
|
||||||
Saqib Ali
|
Saqib Ali
|
||||||
Sara Golemon
|
Sara Golemon
|
||||||
|
Saran Neti
|
||||||
Saul good
|
Saul good
|
||||||
Scott Bailey
|
Scott Bailey
|
||||||
Scott Barrett
|
Scott Barrett
|
||||||
@@ -906,6 +921,7 @@ Steve Oliphant
|
|||||||
Steve Roskowski
|
Steve Roskowski
|
||||||
Steven Bazyl
|
Steven Bazyl
|
||||||
Steven G. Johnson
|
Steven G. Johnson
|
||||||
|
Steven Gu
|
||||||
Steven M. Schweda
|
Steven M. Schweda
|
||||||
Steven Parkes
|
Steven Parkes
|
||||||
Stoned Elipot
|
Stoned Elipot
|
||||||
@@ -943,6 +959,7 @@ Todd Ouska
|
|||||||
Todd Vierling
|
Todd Vierling
|
||||||
Tom Benoist
|
Tom Benoist
|
||||||
Tom Donovan
|
Tom Donovan
|
||||||
|
Tom Grace
|
||||||
Tom Lee
|
Tom Lee
|
||||||
Tom Mattison
|
Tom Mattison
|
||||||
Tom Moers
|
Tom Moers
|
||||||
@@ -994,9 +1011,11 @@ Wesley Laxton
|
|||||||
Wesley Miaw
|
Wesley Miaw
|
||||||
Wez Furlong
|
Wez Furlong
|
||||||
Wilfredo Sanchez
|
Wilfredo Sanchez
|
||||||
|
Willem Sparreboom
|
||||||
Wojciech Zwiefka
|
Wojciech Zwiefka
|
||||||
Wu Yongzheng
|
Wu Yongzheng
|
||||||
Xavier Bouchoux
|
Xavier Bouchoux
|
||||||
|
Yamada Yasuharu
|
||||||
Yang Tse
|
Yang Tse
|
||||||
Yarram Sunil
|
Yarram Sunil
|
||||||
Yehoshua Hershberg
|
Yehoshua Hershberg
|
||||||
@@ -1004,6 +1023,7 @@ Yukihiro Kawada
|
|||||||
Yuriy Sosov
|
Yuriy Sosov
|
||||||
Yves Arrouye
|
Yves Arrouye
|
||||||
Yves Lejeune
|
Yves Lejeune
|
||||||
|
Zdenek Pavlas
|
||||||
Zmey Petroff
|
Zmey Petroff
|
||||||
Zvi Har'El
|
Zvi Har'El
|
||||||
nk
|
nk
|
||||||
|
|||||||
96
docs/TODO
96
docs/TODO
@@ -38,6 +38,7 @@
|
|||||||
5.1 Better persistency for HTTP 1.0
|
5.1 Better persistency for HTTP 1.0
|
||||||
5.2 support FF3 sqlite cookie files
|
5.2 support FF3 sqlite cookie files
|
||||||
5.3 Rearrange request header order
|
5.3 Rearrange request header order
|
||||||
|
5.4 HTTP2/SPDY
|
||||||
|
|
||||||
6. TELNET
|
6. TELNET
|
||||||
6.1 ditch stdin
|
6.1 ditch stdin
|
||||||
@@ -46,19 +47,18 @@
|
|||||||
6.4 send data in chunks
|
6.4 send data in chunks
|
||||||
|
|
||||||
7. SMTP
|
7. SMTP
|
||||||
7.1 Specify the preferred authentication mechanism
|
7.1 Pipelining
|
||||||
7.2 Initial response
|
7.2 Graceful base64 decoding failure
|
||||||
7.3 Pipelining
|
7.3 Enhanced capability support
|
||||||
7.4 Graceful base64 decoding failure
|
|
||||||
|
|
||||||
8. POP3
|
8. POP3
|
||||||
8.1 auth= in URLs
|
8.1 Pipelining
|
||||||
8.2 Initial response
|
8.2 Graceful base64 decoding failure
|
||||||
8.3 Graceful base64 decoding failure
|
8.3 Enhanced capability support
|
||||||
|
|
||||||
9. IMAP
|
9. IMAP
|
||||||
9.1 auth= in URLs
|
9.1 Graceful base64 decoding failure
|
||||||
9.2 Graceful base64 decoding failure
|
9.2 Enhanced capability support
|
||||||
|
|
||||||
10. LDAP
|
10. LDAP
|
||||||
10.1 SASL based authentication mechanisms
|
10.1 SASL based authentication mechanisms
|
||||||
@@ -269,6 +269,25 @@
|
|||||||
headers use a default value so only headers that need to be moved have to be
|
headers use a default value so only headers that need to be moved have to be
|
||||||
specified.
|
specified.
|
||||||
|
|
||||||
|
5.4 HTTP2/SPDY
|
||||||
|
|
||||||
|
The first drafts for HTTP2 have been published
|
||||||
|
(http://tools.ietf.org/html/draft-ietf-httpbis-http2-03) and is so far based
|
||||||
|
on SPDY (http://www.chromium.org/spdy) designs and experiences. Chances are
|
||||||
|
it will end up in that style. Chrome and Firefox already support SPDY and
|
||||||
|
lots of web services do.
|
||||||
|
|
||||||
|
It would make sense to implement SPDY support now and later transition into
|
||||||
|
or add HTTP2 support as well.
|
||||||
|
|
||||||
|
We should base or HTTP2/SPDY work on a 3rd party library for the protocol
|
||||||
|
fiddling. The Spindy library (http://spindly.haxx.se/) was an attempt to make
|
||||||
|
such a library with an API suitable for use by libcurl but that effort has
|
||||||
|
more or less stalled. spdylay (https://github.com/tatsuhiro-t/spdylay) may
|
||||||
|
be a better option, either used directly or wrapped with a more spindly-like
|
||||||
|
API.
|
||||||
|
|
||||||
|
|
||||||
6. TELNET
|
6. TELNET
|
||||||
|
|
||||||
6.1 ditch stdin
|
6.1 ditch stdin
|
||||||
@@ -295,65 +314,54 @@ to provide the data to send.
|
|||||||
|
|
||||||
7. SMTP
|
7. SMTP
|
||||||
|
|
||||||
7.1 Specify the preferred authentication mechanism
|
7.1 Pipelining
|
||||||
|
|
||||||
Add the ability to specify the preferred authentication mechanism or a list
|
|
||||||
of mechanisms that should be used. Not only that, but the order that is
|
|
||||||
returned by the server during the EHLO response should be honored by curl.
|
|
||||||
|
|
||||||
7.2 Initial response
|
|
||||||
|
|
||||||
Add the ability for the user to specify whether the initial response is
|
|
||||||
included in the AUTH command. Some email servers, such as Microsoft
|
|
||||||
Exchange, can work with either whilst others need to have the initial
|
|
||||||
response sent separately:
|
|
||||||
|
|
||||||
http://curl.haxx.se/mail/lib-2012-03/0114.html
|
|
||||||
|
|
||||||
7.3 Pipelining
|
|
||||||
|
|
||||||
Add support for pipelining emails.
|
Add support for pipelining emails.
|
||||||
|
|
||||||
7.4 Graceful base64 decoding failure
|
7.2 Graceful base64 decoding failure
|
||||||
|
|
||||||
Rather than shutting down the session and returning an error when the
|
Rather than shutting down the session and returning an error when the
|
||||||
decoding of a base64 encoded authentication response fails, we should
|
decoding of a base64 encoded authentication response fails, we should
|
||||||
gracefully shutdown the authentication process by sending a * response to the
|
gracefully shutdown the authentication process by sending a * response to the
|
||||||
server as per RFC4954.
|
server as per RFC4954.
|
||||||
|
|
||||||
|
7.3 Enhanced capability support
|
||||||
|
|
||||||
|
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||||
|
capabilities returned from the EHLO command.
|
||||||
|
|
||||||
8. POP3
|
8. POP3
|
||||||
|
|
||||||
8.1 auth= in URLs
|
8.1 Pipelining
|
||||||
|
|
||||||
Being able to specify the preferred authentication mechanism in the URL as
|
Add support for pipelining commands.
|
||||||
per RFC2384.
|
|
||||||
|
|
||||||
8.2 Initial response
|
8.2 Graceful base64 decoding failure
|
||||||
|
|
||||||
Add the ability for the user to specify whether the initial response is
|
|
||||||
included in the AUTH command as per RFC5034.
|
|
||||||
|
|
||||||
8.3 Graceful base64 decoding failure
|
|
||||||
|
|
||||||
Rather than shutting down the session and returning an error when the
|
Rather than shutting down the session and returning an error when the
|
||||||
decoding of a base64 encoded authentication response fails, we should
|
decoding of a base64 encoded authentication response fails, we should
|
||||||
gracefully shutdown the authentication process by sending a * response to the
|
gracefully shutdown the authentication process by sending a * response to the
|
||||||
server as per RFC5034.
|
server as per RFC5034.
|
||||||
|
|
||||||
|
8.3 Enhanced capability support
|
||||||
|
|
||||||
|
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||||
|
capabilities returned from the CAPA command.
|
||||||
|
|
||||||
9. IMAP
|
9. IMAP
|
||||||
|
|
||||||
9.1 auth= in URLs
|
9.1 Graceful base64 decoding failure
|
||||||
|
|
||||||
Being able to specify the preferred authentication mechanism in the URL as
|
|
||||||
per RFC5092.
|
|
||||||
|
|
||||||
9.2 Graceful base64 decoding failure
|
|
||||||
|
|
||||||
Rather than shutting down the session and returning an error when the
|
Rather than shutting down the session and returning an error when the
|
||||||
decoding of a base64 encoded authentication response fails, we should
|
decoding of a base64 encoded authentication response fails, we should
|
||||||
gracefully shutdown the authentication process by sending a * response to the
|
gracefully shutdown the authentication process by sending a * response to the
|
||||||
server as per RFC3501.
|
server as per RFC3501.
|
||||||
|
|
||||||
|
9.2 Enhanced capability support
|
||||||
|
|
||||||
|
Add the ability, for an application that uses libcurl, to obtain the list of
|
||||||
|
capabilities returned from the CAPABILITY command.
|
||||||
|
|
||||||
10. LDAP
|
10. LDAP
|
||||||
|
|
||||||
10.1 SASL based authentication mechanisms
|
10.1 SASL based authentication mechanisms
|
||||||
@@ -429,6 +437,12 @@ to provide the data to send.
|
|||||||
keys and certs over DNS using DNSSEC as an alternative to the CA model.
|
keys and certs over DNS using DNSSEC as an alternative to the CA model.
|
||||||
http://www.rfc-editor.org/rfc/rfc6698.txt
|
http://www.rfc-editor.org/rfc/rfc6698.txt
|
||||||
|
|
||||||
|
An initial patch was posted by Suresh Krishnaswamy on March 7th 2013
|
||||||
|
(http://curl.haxx.se/mail/lib-2013-03/0075.html) but it was a too simple
|
||||||
|
approach. See Daniel's comments:
|
||||||
|
http://curl.haxx.se/mail/lib-2013-03/0103.html . libunbound may be the
|
||||||
|
correct library to base this development on.
|
||||||
|
|
||||||
13. GnuTLS
|
13. GnuTLS
|
||||||
|
|
||||||
13.1 SSL engine stuff
|
13.1 SSL engine stuff
|
||||||
|
|||||||
14
docs/curl.1
14
docs/curl.1
@@ -5,7 +5,7 @@
|
|||||||
.\" * | (__| |_| | _ <| |___
|
.\" * | (__| |_| | _ <| |___
|
||||||
.\" * \___|\___/|_| \_\_____|
|
.\" * \___|\___/|_| \_\_____|
|
||||||
.\" *
|
.\" *
|
||||||
.\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
.\" *
|
.\" *
|
||||||
.\" * This software is licensed as described in the file COPYING, which
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
@@ -388,7 +388,12 @@ curl the nickname of the certificate to use within the NSS database defined
|
|||||||
by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the
|
by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the
|
||||||
NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be
|
NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be
|
||||||
loaded. If you want to use a file from the current directory, please precede
|
loaded. If you want to use a file from the current directory, please precede
|
||||||
it with "./" prefix, in order to avoid confusion with a nickname.
|
it with "./" prefix, in order to avoid confusion with a nickname. If the
|
||||||
|
nickname contains ":", it needs to be preceded by "\\" so that it is not
|
||||||
|
recognized as password delimiter. If the nickname contains "\\", it needs to
|
||||||
|
be escaped as "\\\\" so that it is not recognized as an escape character.
|
||||||
|
|
||||||
|
(iOS and Mac OS X only) If curl is built against Secure Transport, then the certificate string must match the name of a certificate that's in the system or user keychain. The private key corresponding to the certificate, and certificate chain (if any), must also be present in the keychain.
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "--engine <name>"
|
.IP "--engine <name>"
|
||||||
@@ -1272,8 +1277,9 @@ Set this option to zero to not timeout retries. (Added in 7.12.3)
|
|||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-s, --silent"
|
.IP "-s, --silent"
|
||||||
Silent or quiet mode. Don't show progress meter or error messages. Makes
|
Silent or quiet mode. Don't show progress meter or error messages. Makes Curl
|
||||||
Curl mute.
|
mute. It will still output the data you ask for, potentially even to the
|
||||||
|
terminal/stdout unless you redirect it.
|
||||||
.IP "-S, --show-error"
|
.IP "-S, --show-error"
|
||||||
When used with \fI-s\fP it makes curl show an error message if it fails.
|
When used with \fI-s\fP it makes curl show an error message if it fails.
|
||||||
.IP "--ssl"
|
.IP "--ssl"
|
||||||
|
|||||||
2
docs/examples/.gitignore
vendored
2
docs/examples/.gitignore
vendored
@@ -43,3 +43,5 @@ simplessl
|
|||||||
smtp-multi
|
smtp-multi
|
||||||
smtp-tls
|
smtp-tls
|
||||||
url2file
|
url2file
|
||||||
|
usercertinmem
|
||||||
|
xmlstream
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
|
|||||||
persistant post-callback postit2 sepheaders simple simplepost simplessl \
|
persistant post-callback postit2 sepheaders simple simplepost simplessl \
|
||||||
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
|
sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard \
|
||||||
smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \
|
smtp-multi simplesmtp smtp-tls rtsp externalsocket resolve \
|
||||||
progressfunc pop3s pop3slist imap url2file sftpget ftpsget
|
progressfunc pop3s pop3slist imap url2file sftpget ftpsget \
|
||||||
|
usercertinmem
|
||||||
|
|
||||||
# These examples require external dependencies that may not be commonly
|
# These examples require external dependencies that may not be commonly
|
||||||
# available on POSIX systems, so don't bother attempting to compile them here.
|
# available on POSIX systems, so don't bother attempting to compile them here.
|
||||||
@@ -13,4 +14,4 @@ COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c \
|
|||||||
ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
|
ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c \
|
||||||
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
|
opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
|
||||||
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
|
smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp \
|
||||||
multi-uv.c
|
multi-uv.c xmlstream.c
|
||||||
|
|||||||
@@ -27,14 +27,14 @@
|
|||||||
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-spi-winidn
|
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-spi-winidn
|
||||||
##
|
##
|
||||||
## Hint: you can also set environment vars to control the build, f.e.:
|
## Hint: you can also set environment vars to control the build, f.e.:
|
||||||
## set ZLIB_PATH=c:/zlib-1.2.7
|
## set ZLIB_PATH=c:/zlib-1.2.8
|
||||||
## set ZLIB=1
|
## set ZLIB=1
|
||||||
#
|
#
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
ifndef ZLIB_PATH
|
ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ../../../zlib-1.2.7
|
ZLIB_PATH = ../../../zlib-1.2.8
|
||||||
endif
|
endif
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ endif
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
ifndef ZLIB_PATH
|
ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ../../../zlib-1.2.7
|
ZLIB_PATH = ../../../zlib-1.2.8
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
|
|||||||
@@ -78,4 +78,5 @@ simplepost.c - HTTP POST
|
|||||||
simplessl.c - HTTPS example with certificates many options set
|
simplessl.c - HTTPS example with certificates many options set
|
||||||
synctime.c - Sync local time by extracting date from remote HTTP servers
|
synctime.c - Sync local time by extracting date from remote HTTP servers
|
||||||
url2file.c - download a document and store it in a file
|
url2file.c - download a document and store it in a file
|
||||||
|
xmlstream.c - Stream-parse a document using the streaming Expat parser
|
||||||
10-at-a-time.c - Download many files simultaneously, 10 at a time.
|
10-at-a-time.c - Download many files simultaneously, 10 at a time.
|
||||||
|
|||||||
@@ -54,23 +54,22 @@ int main(void)
|
|||||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
|
||||||
|
|
||||||
/* open the files */
|
/* open the files */
|
||||||
headerfile = fopen(headerfilename,"w");
|
headerfile = fopen(headerfilename,"wb");
|
||||||
if (headerfile == NULL) {
|
if (headerfile == NULL) {
|
||||||
curl_easy_cleanup(curl_handle);
|
curl_easy_cleanup(curl_handle);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bodyfile = fopen(bodyfilename,"w");
|
bodyfile = fopen(bodyfilename,"wb");
|
||||||
if (bodyfile == NULL) {
|
if (bodyfile == NULL) {
|
||||||
curl_easy_cleanup(curl_handle);
|
curl_easy_cleanup(curl_handle);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we want the headers to this file handle */
|
/* we want the headers be written to this file handle */
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, headerfile);
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, headerfile);
|
||||||
|
|
||||||
/*
|
/* we want the body be written to this file handle instead of stdout */
|
||||||
* Notice here that if you want the actual data sent anywhere else but
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bodyfile);
|
||||||
* stdout, you should consider using the CURLOPT_WRITEDATA option. */
|
|
||||||
|
|
||||||
/* get it! */
|
/* get it! */
|
||||||
curl_easy_perform(curl_handle);
|
curl_easy_perform(curl_handle);
|
||||||
@@ -78,6 +77,9 @@ int main(void)
|
|||||||
/* close the header file */
|
/* close the header file */
|
||||||
fclose(headerfile);
|
fclose(headerfile);
|
||||||
|
|
||||||
|
/* close the body file */
|
||||||
|
fclose(bodyfile);
|
||||||
|
|
||||||
/* cleanup curl stuff */
|
/* cleanup curl stuff */
|
||||||
curl_easy_cleanup(curl_handle);
|
curl_easy_cleanup(curl_handle);
|
||||||
|
|
||||||
|
|||||||
211
docs/examples/usercertinmem.c
Normal file
211
docs/examples/usercertinmem.c
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
/* Example using an in memory PEM user certificate and RSA key to retrieve an
|
||||||
|
* https page.
|
||||||
|
* Written by Ishan SinghLevett, based on Theo Borm's cacertinmem.c.
|
||||||
|
* Note this example does not use a CA certificate, however one should be used
|
||||||
|
* if you want a properly secure connection
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||||
|
{
|
||||||
|
fwrite(ptr,size,nmemb,stream);
|
||||||
|
return(nmemb*size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
|
||||||
|
{
|
||||||
|
X509 *cert = NULL;
|
||||||
|
BIO *bio = NULL;
|
||||||
|
BIO *kbio = NULL;
|
||||||
|
RSA *rsa = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
const char *mypem = /* www.cacert.org */
|
||||||
|
"-----BEGIN CERTIFICATE-----\n"\
|
||||||
|
"MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"\
|
||||||
|
"IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"\
|
||||||
|
"IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n"\
|
||||||
|
"Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n"\
|
||||||
|
"BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi\n"\
|
||||||
|
"MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ\n"\
|
||||||
|
"ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC\n"\
|
||||||
|
"CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ\n"\
|
||||||
|
"8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6\n"\
|
||||||
|
"zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y\n"\
|
||||||
|
"fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7\n"\
|
||||||
|
"w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc\n"\
|
||||||
|
"G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k\n"\
|
||||||
|
"epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q\n"\
|
||||||
|
"laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ\n"\
|
||||||
|
"QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU\n"\
|
||||||
|
"fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826\n"\
|
||||||
|
"YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w\n"\
|
||||||
|
"ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY\n"\
|
||||||
|
"gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe\n"\
|
||||||
|
"MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0\n"\
|
||||||
|
"IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy\n"\
|
||||||
|
"dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw\n"\
|
||||||
|
"czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0\n"\
|
||||||
|
"dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl\n"\
|
||||||
|
"aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC\n"\
|
||||||
|
"AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg\n"\
|
||||||
|
"b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB\n"\
|
||||||
|
"ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc\n"\
|
||||||
|
"nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg\n"\
|
||||||
|
"18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c\n"\
|
||||||
|
"gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl\n"\
|
||||||
|
"Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY\n"\
|
||||||
|
"sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T\n"\
|
||||||
|
"SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF\n"\
|
||||||
|
"CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum\n"\
|
||||||
|
"GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n"\
|
||||||
|
"zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n"\
|
||||||
|
"omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\
|
||||||
|
"-----END CERTIFICATE-----\n";
|
||||||
|
|
||||||
|
/*replace the XXX with the actual RSA key*/
|
||||||
|
const char *mykey =
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"\
|
||||||
|
"-----END RSA PRIVATE KEY-----\n";
|
||||||
|
|
||||||
|
(void)curl; /* avoid warnings */
|
||||||
|
(void)parm; /* avoid warnings */
|
||||||
|
|
||||||
|
/* get a BIO */
|
||||||
|
bio = BIO_new_mem_buf((char *)mypem, -1);
|
||||||
|
|
||||||
|
if (bio == NULL) {
|
||||||
|
printf("BIO_new_mem_buf failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use it to read the PEM formatted certificate from memory into an X509
|
||||||
|
* structure that SSL can use
|
||||||
|
*/
|
||||||
|
cert = PEM_read_bio_X509(bio, NULL, 0, NULL);
|
||||||
|
if (cert == NULL) {
|
||||||
|
printf("PEM_read_bio_X509 failed...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*tell SSL to use the X509 certificate*/
|
||||||
|
ret = SSL_CTX_use_certificate((SSL_CTX*)sslctx, cert);
|
||||||
|
if (ret != 1) {
|
||||||
|
printf("Use certificate failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*create a bio for the RSA key*/
|
||||||
|
kbio = BIO_new_mem_buf((char *)mykey, -1);
|
||||||
|
if (kbio == NULL) {
|
||||||
|
printf("BIO_new_mem_buf failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*read the key bio into an RSA object*/
|
||||||
|
rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
|
||||||
|
if (rsa == NULL) {
|
||||||
|
printf("Failed to create key bio\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*tell SSL to use the RSA key from memory*/
|
||||||
|
ret = SSL_CTX_use_RSAPrivateKey((SSL_CTX*)sslctx, rsa);
|
||||||
|
if (ret != 1) {
|
||||||
|
printf("Use Key failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* all set to go */
|
||||||
|
return CURLE_OK ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *ch;
|
||||||
|
CURLcode rv;
|
||||||
|
|
||||||
|
rv = curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
ch = curl_easy_init();
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_VERBOSE, 0L);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_HEADER, 0L);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_NOPROGRESS, 1L);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_NOSIGNAL, 1L);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_WRITEFUNCTION, *writefunction);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_WRITEDATA, stdout);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_HEADERFUNCTION, *writefunction);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_WRITEHEADER, stderr);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_SSLCERTTYPE,"PEM");
|
||||||
|
|
||||||
|
/* both VERIFYPEER and VERIFYHOST are set to 0 in this case because there is
|
||||||
|
no CA certificate*/
|
||||||
|
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
|
rv = curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
|
||||||
|
rv = curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM");
|
||||||
|
|
||||||
|
/* first try: retrieve page without user certificate and key -> will fail
|
||||||
|
*/
|
||||||
|
rv = curl_easy_perform(ch);
|
||||||
|
if (rv==CURLE_OK) {
|
||||||
|
printf("*** transfer succeeded ***\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("*** transfer failed ***\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* second try: retrieve page using user certificate and key -> will succeed
|
||||||
|
* load the certificate and key by installing a function doing the necessary
|
||||||
|
* "modifications" to the SSL CONTEXT just before link init
|
||||||
|
*/
|
||||||
|
rv = curl_easy_setopt(ch,CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
|
||||||
|
rv = curl_easy_perform(ch);
|
||||||
|
if (rv==CURLE_OK) {
|
||||||
|
printf("*** transfer succeeded ***\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("*** transfer failed ***\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_cleanup(ch);
|
||||||
|
curl_global_cleanup();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
158
docs/examples/xmlstream.c
Normal file
158
docs/examples/xmlstream.c
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
*
|
||||||
|
* This software is licensed as described in the file COPYING, which
|
||||||
|
* you should have received as part of this distribution. The terms
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
/* Stream-parse a document using the streaming Expat parser.
|
||||||
|
* Written by David Strauss
|
||||||
|
*
|
||||||
|
* Expat => http://www.libexpat.org/
|
||||||
|
*
|
||||||
|
* gcc -Wall -I/usr/local/include xmlstream.c -lcurl -lexpat -o xmlstream
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <expat.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
struct MemoryStruct {
|
||||||
|
char *memory;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParserStruct {
|
||||||
|
int ok;
|
||||||
|
size_t tags;
|
||||||
|
size_t depth;
|
||||||
|
struct MemoryStruct characters;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void startElement(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||||
|
{
|
||||||
|
struct ParserStruct *state = (struct ParserStruct *) userData;
|
||||||
|
state->tags++;
|
||||||
|
state->depth++;
|
||||||
|
|
||||||
|
/* Get a clean slate for reading in character data. */
|
||||||
|
free(state->characters.memory);
|
||||||
|
state->characters.memory = NULL;
|
||||||
|
state->characters.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void characterDataHandler(void *userData, const XML_Char *s, int len)
|
||||||
|
{
|
||||||
|
struct ParserStruct *state = (struct ParserStruct *) userData;
|
||||||
|
struct MemoryStruct *mem = &state->characters;
|
||||||
|
|
||||||
|
mem->memory = realloc(mem->memory, mem->size + len + 1);
|
||||||
|
if(mem->memory == NULL) {
|
||||||
|
/* Out of memory. */
|
||||||
|
fprintf(stderr, "Not enough memory (realloc returned NULL).\n");
|
||||||
|
state->ok = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&(mem->memory[mem->size]), s, len);
|
||||||
|
mem->size += len;
|
||||||
|
mem->memory[mem->size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void endElement(void *userData, const XML_Char *name)
|
||||||
|
{
|
||||||
|
struct ParserStruct *state = (struct ParserStruct *) userData;
|
||||||
|
state->depth--;
|
||||||
|
|
||||||
|
printf("%5lu %10lu %s\n", state->depth, state->characters.size, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t parseStreamCallback(void *contents, size_t length, size_t nmemb, void *userp)
|
||||||
|
{
|
||||||
|
XML_Parser parser = (XML_Parser) userp;
|
||||||
|
size_t real_size = length * nmemb;
|
||||||
|
struct ParserStruct *state = (struct ParserStruct *) XML_GetUserData(parser);
|
||||||
|
|
||||||
|
/* Only parse if we're not already in a failure state. */
|
||||||
|
if (state->ok && XML_Parse(parser, contents, real_size, 0) == 0) {
|
||||||
|
int error_code = XML_GetErrorCode(parser);
|
||||||
|
fprintf(stderr, "Parsing response buffer of length %lu failed with error code %d (%s).\n",
|
||||||
|
real_size, error_code, XML_ErrorString(error_code));
|
||||||
|
state->ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
CURL *curl_handle;
|
||||||
|
CURLcode res;
|
||||||
|
XML_Parser parser;
|
||||||
|
struct ParserStruct state;
|
||||||
|
|
||||||
|
/* Initialize the state structure for parsing. */
|
||||||
|
memset(&state, 0, sizeof(struct ParserStruct));
|
||||||
|
state.ok = 1;
|
||||||
|
|
||||||
|
/* Initialize a namespace-aware parser. */
|
||||||
|
parser = XML_ParserCreateNS(NULL, '\0');
|
||||||
|
XML_SetUserData(parser, &state);
|
||||||
|
XML_SetElementHandler(parser, startElement, endElement);
|
||||||
|
XML_SetCharacterDataHandler(parser, characterDataHandler);
|
||||||
|
|
||||||
|
/* Initalize a libcurl handle. */
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL ^ CURL_GLOBAL_SSL);
|
||||||
|
curl_handle = curl_easy_init();
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.w3schools.com/xml/simple.xml");
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, parseStreamCallback);
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)parser);
|
||||||
|
|
||||||
|
printf("Depth Characters Closing Tag\n");
|
||||||
|
|
||||||
|
/* Perform the request and any follow-up parsing. */
|
||||||
|
res = curl_easy_perform(curl_handle);
|
||||||
|
if(res != CURLE_OK) {
|
||||||
|
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||||
|
curl_easy_strerror(res));
|
||||||
|
}
|
||||||
|
else if (state.ok) {
|
||||||
|
/* Expat requires one final call to finalize parsing. */
|
||||||
|
if (XML_Parse(parser, NULL, 0, 1) == 0) {
|
||||||
|
int error_code = XML_GetErrorCode(parser);
|
||||||
|
fprintf(stderr, "Finalizing parsing failed with error code %d (%s).\n",
|
||||||
|
error_code, XML_ErrorString(error_code));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(" --------------\n");
|
||||||
|
printf(" %lu tags total\n", state.tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up. */
|
||||||
|
free(state.characters.memory);
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
curl_easy_cleanup(curl_handle);
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -342,15 +342,34 @@ argument in the closesocket callback set with
|
|||||||
The default value of this parameter is unspecified.
|
The default value of this parameter is unspecified.
|
||||||
(Option added in 7.21.7)
|
(Option added in 7.21.7)
|
||||||
.IP CURLOPT_PROGRESSFUNCTION
|
.IP CURLOPT_PROGRESSFUNCTION
|
||||||
Pass a pointer to a function that matches the following prototype: \fBint
|
Pass a pointer to a function that matches the following prototype:
|
||||||
function(void *clientp, double dltotal, double dlnow, double ultotal, double
|
|
||||||
ulnow); \fP. This function gets called by libcurl instead of its internal
|
\fBint function(void *clientp, double dltotal, double dlnow, double ultotal,
|
||||||
equivalent with a frequent interval during operation (roughly once per second
|
double ulnow);\fP
|
||||||
or sooner) no matter if data is being transferred or not. Unknown/unused
|
|
||||||
argument values passed to the callback will be set to zero (like if you only
|
This function gets called by libcurl instead of its internal equivalent with a
|
||||||
download data, the upload size will remain 0). Returning a non-zero value from
|
frequent interval. While data is being transferred it will be called very
|
||||||
this callback will cause libcurl to abort the transfer and return
|
frequently, and during slow periods like when nothing is being transferred it
|
||||||
\fICURLE_ABORTED_BY_CALLBACK\fP.
|
can slow down to about one call per second.
|
||||||
|
|
||||||
|
\fIclientp\fP is the pointer set with \fICURLOPT_PROGRESSDATA\fP, it is not
|
||||||
|
actually used by libcurl but is only passed along from the application to the
|
||||||
|
callback.
|
||||||
|
|
||||||
|
The callback gets told how much data libcurl will transfer and has
|
||||||
|
transferred, in number of bytes. \fIdltotal\fP is the total number of bytes
|
||||||
|
libcurl expects to download in this transfer. \fIdlnow\fP is the number of
|
||||||
|
bytes downloaded so far. \fIultotal\fP is the total number of bytes libcurl
|
||||||
|
expects to upload in this transfer. \fIulnow\fP is the number of bytes
|
||||||
|
uploaded so far.
|
||||||
|
|
||||||
|
Unknown/unused argument values passed to the callback will be set to zero
|
||||||
|
(like if you only download data, the upload size will remain 0). Many times
|
||||||
|
the callback will be called one or more times first, before it knows the data
|
||||||
|
sizes so a program must be made to handle that.
|
||||||
|
|
||||||
|
Returning a non-zero value from this callback will cause libcurl to abort the
|
||||||
|
transfer and return \fICURLE_ABORTED_BY_CALLBACK\fP.
|
||||||
|
|
||||||
If you transfer data with the multi interface, this function will not be
|
If you transfer data with the multi interface, this function will not be
|
||||||
called during periods of idleness unless you call the appropriate libcurl
|
called during periods of idleness unless you call the appropriate libcurl
|
||||||
@@ -620,12 +639,20 @@ scheme://host:port/path
|
|||||||
|
|
||||||
For a greater explanation of the format please see RFC3986.
|
For a greater explanation of the format please see RFC3986.
|
||||||
|
|
||||||
If the given URL lacks the scheme, or protocol, part ("http://" or "ftp://"
|
If the given URL lacks the scheme (such as "http://" or "ftp://" etc) then
|
||||||
etc), libcurl will attempt to resolve which protocol to use based on the
|
libcurl will attempt to resolve the protocol based on one of the following
|
||||||
given host mame. If the protocol is not supported, libcurl will return
|
given host names:
|
||||||
(\fICURLE_UNSUPPORTED_PROTOCOL\fP) when you call \fIcurl_easy_perform(3)\fP
|
|
||||||
or \fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed
|
HTTP, FTP, DICT, LDAP, IMAP, POP3 or SMTP
|
||||||
information on which protocols are supported.
|
|
||||||
|
(POP3 and SMTP added in 7.31.0)
|
||||||
|
|
||||||
|
Should the protocol, either that specified by the scheme or deduced by libcurl
|
||||||
|
from the host name, not be supported by libcurl then
|
||||||
|
(\fICURLE_UNSUPPORTED_PROTOCOL\fP) will be returned from either the
|
||||||
|
\fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP functions when you
|
||||||
|
call them. Use \fIcurl_version_info(3)\fP for detailed information of which
|
||||||
|
protocols are supported by the build of libcurl you are using.
|
||||||
|
|
||||||
The host part of the URL contains the address of the server that you want to
|
The host part of the URL contains the address of the server that you want to
|
||||||
connect to. This can be the fully qualified domain name of the server, the
|
connect to. This can be the fully qualified domain name of the server, the
|
||||||
@@ -640,17 +667,23 @@ http://192.168.0.1/
|
|||||||
|
|
||||||
http://[2001:1890:1112:1::20]/
|
http://[2001:1890:1112:1::20]/
|
||||||
|
|
||||||
It is also possible to specify the user name and password as part of the
|
It is also possible to specify the user name, password and any supported login
|
||||||
host, for some protocols, when connecting to servers that require
|
options as part of the host, for the following protocols, when connecting to
|
||||||
authentication.
|
servers that require authentication:
|
||||||
|
|
||||||
For example the following types of authentication support this:
|
|
||||||
|
|
||||||
http://user:password@www.example.com
|
http://user:password@www.example.com
|
||||||
|
|
||||||
ftp://user:password@ftp.example.com
|
ftp://user:password@ftp.example.com
|
||||||
|
|
||||||
pop3://user:password@mail.example.com
|
imap://user:password;options@mail.example.com
|
||||||
|
|
||||||
|
pop3://user:password;options@mail.example.com
|
||||||
|
|
||||||
|
smtp://user:password;options@mail.example.com
|
||||||
|
|
||||||
|
At present only IMAP, POP3 and SMTP support login options as part of the host.
|
||||||
|
For more information about the login options in URL syntax please see RFC2384,
|
||||||
|
RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
|
||||||
|
|
||||||
The port is optional and when not specified libcurl will use the default port
|
The port is optional and when not specified libcurl will use the default port
|
||||||
based on the determined or specified protocol: 80 for HTTP, 21 for FTP and 25
|
based on the determined or specified protocol: 80 for HTTP, 21 for FTP and 25
|
||||||
@@ -1040,8 +1073,8 @@ the full path name to the file you want libcurl to use as .netrc file. If this
|
|||||||
option is omitted, and \fICURLOPT_NETRC\fP is set, libcurl will attempt to
|
option is omitted, and \fICURLOPT_NETRC\fP is set, libcurl will attempt to
|
||||||
find a .netrc file in the current user's home directory. (Added in 7.10.9)
|
find a .netrc file in the current user's home directory. (Added in 7.10.9)
|
||||||
.IP CURLOPT_USERPWD
|
.IP CURLOPT_USERPWD
|
||||||
Pass a char * as parameter, which should be [user name]:[password] to use for
|
Pass a char * as parameter, pointing to a zero terminated login details string
|
||||||
the connection. Use \fICURLOPT_HTTPAUTH\fP to decide the authentication method.
|
for the connection. The format of which is: [user name]:[password];[options].
|
||||||
|
|
||||||
When using NTLM, you can set the domain by prepending it to the user name and
|
When using NTLM, you can set the domain by prepending it to the user name and
|
||||||
separating the domain and name with a forward (/) or backward slash (\\). Like
|
separating the domain and name with a forward (/) or backward slash (\\). Like
|
||||||
@@ -1054,10 +1087,18 @@ and password information to hosts using the initial host name (unless
|
|||||||
\fICURLOPT_UNRESTRICTED_AUTH\fP is set), so if libcurl follows locations to
|
\fICURLOPT_UNRESTRICTED_AUTH\fP is set), so if libcurl follows locations to
|
||||||
other hosts it will not send the user and password to those. This is enforced
|
other hosts it will not send the user and password to those. This is enforced
|
||||||
to prevent accidental information leakage.
|
to prevent accidental information leakage.
|
||||||
|
|
||||||
|
At present only IMAP, POP3 and SMTP support login options as part of the
|
||||||
|
details string. For more information about the login options please see
|
||||||
|
RFC2384, RFC5092 and IETF draft draft-earhart-url-smtp-00.txt (Added in 7.31.0).
|
||||||
|
|
||||||
|
Use \fICURLOPT_HTTPAUTH\fP to specify the authentication method for HTTP based
|
||||||
|
connections.
|
||||||
.IP CURLOPT_PROXYUSERPWD
|
.IP CURLOPT_PROXYUSERPWD
|
||||||
Pass a char * as parameter, which should be [user name]:[password] to use for
|
Pass a char * as parameter, which should be [user name]:[password] to use for
|
||||||
the connection to the HTTP proxy. Use \fICURLOPT_PROXYAUTH\fP to decide
|
the connection to the HTTP proxy.
|
||||||
the authentication method.
|
|
||||||
|
Use \fICURLOPT_PROXYAUTH\fP to specify the authentication method.
|
||||||
.IP CURLOPT_USERNAME
|
.IP CURLOPT_USERNAME
|
||||||
Pass a char * as parameter, which should be pointing to the zero terminated
|
Pass a char * as parameter, which should be pointing to the zero terminated
|
||||||
user name to use for the transfer.
|
user name to use for the transfer.
|
||||||
@@ -1134,7 +1175,7 @@ Microsoft. It uses a challenge-response and hash concept similar to Digest, to
|
|||||||
prevent the password from being eavesdropped.
|
prevent the password from being eavesdropped.
|
||||||
|
|
||||||
You need to build libcurl with either OpenSSL, GnuTLS or NSS support for this
|
You need to build libcurl with either OpenSSL, GnuTLS or NSS support for this
|
||||||
option to work, or build libcurl on Windows.
|
option to work, or build libcurl on Windows with SSPI support.
|
||||||
.IP CURLAUTH_NTLM_WB
|
.IP CURLAUTH_NTLM_WB
|
||||||
NTLM delegating to winbind helper. Authentication is performed by a separate
|
NTLM delegating to winbind helper. Authentication is performed by a separate
|
||||||
binary application that is executed when needed. The name of the application
|
binary application that is executed when needed. The name of the application
|
||||||
@@ -1195,6 +1236,15 @@ actual name and password with the \fICURLOPT_PROXYUSERPWD\fP option. The
|
|||||||
bitmask can be constructed by or'ing together the bits listed above for the
|
bitmask can be constructed by or'ing together the bits listed above for the
|
||||||
\fICURLOPT_HTTPAUTH\fP option. As of this writing, only Basic, Digest and NTLM
|
\fICURLOPT_HTTPAUTH\fP option. As of this writing, only Basic, Digest and NTLM
|
||||||
work. (Added in 7.10.7)
|
work. (Added in 7.10.7)
|
||||||
|
.IP CURLOPT_SASL_IR
|
||||||
|
Pass a long. If the value is 1, curl will send the initial response to the
|
||||||
|
server in the first authentication packet in order to reduce the number of
|
||||||
|
ping pong requests. Only applicable to supporting SASL authentication
|
||||||
|
mechanisms and to the IMAP, POP3 and SMTP protocols. (Added in 7.31.0)
|
||||||
|
|
||||||
|
Note: Whilst IMAP supports this option there is no need to explicitly set it,
|
||||||
|
as libcurl can determine the feature itself when the server supports the
|
||||||
|
SASL-IR CAPABILITY.
|
||||||
.SH HTTP OPTIONS
|
.SH HTTP OPTIONS
|
||||||
.IP CURLOPT_AUTOREFERER
|
.IP CURLOPT_AUTOREFERER
|
||||||
Pass a parameter set to 1 to enable this. When enabled, libcurl will
|
Pass a parameter set to 1 to enable this. When enabled, libcurl will
|
||||||
@@ -1392,10 +1442,12 @@ internally, your added one will be used instead. If you add a header with no
|
|||||||
content as in 'Accept:' (no data on the right side of the colon), the
|
content as in 'Accept:' (no data on the right side of the colon), the
|
||||||
internally used header will get disabled. Thus, using this option you can add
|
internally used header will get disabled. Thus, using this option you can add
|
||||||
new headers, replace internal headers and remove internal headers. To add a
|
new headers, replace internal headers and remove internal headers. To add a
|
||||||
header with no content, make the content be two quotes: \&"". The headers
|
header with no content (nothing to the right side of the colon), use the
|
||||||
included in the linked list must not be CRLF-terminated, because curl adds
|
form 'MyHeader;' (note the ending semicolon).
|
||||||
CRLF after each header item. Failure to comply with this will result in
|
|
||||||
strange bugs because the server will most likely ignore part of the headers
|
The headers included in the linked list must not be CRLF-terminated, because
|
||||||
|
curl adds CRLF after each header item. Failure to comply with this will result
|
||||||
|
in strange bugs because the server will most likely ignore part of the headers
|
||||||
you specified.
|
you specified.
|
||||||
|
|
||||||
The first line in a request (containing the method, usually a GET or POST) is
|
The first line in a request (containing the method, usually a GET or POST) is
|
||||||
@@ -2208,6 +2260,12 @@ changed with \fICURLOPT_SSLCERTTYPE\fP.
|
|||||||
With NSS this can also be the nickname of the certificate you wish to
|
With NSS this can also be the nickname of the certificate you wish to
|
||||||
authenticate with. If you want to use a file from the current directory, please
|
authenticate with. If you want to use a file from the current directory, please
|
||||||
precede it with "./" prefix, in order to avoid confusion with a nickname.
|
precede it with "./" prefix, in order to avoid confusion with a nickname.
|
||||||
|
|
||||||
|
(iOS and Mac OS X only) With Secure Transport, this string must match the name
|
||||||
|
of a certificate that's in the system or user keychain. You should encode this
|
||||||
|
string in UTF-8 format in case it contains non-ASCII characters. The private
|
||||||
|
key corresponding to the certificate, and certificate chain (if any), must
|
||||||
|
also be present in the keychain. (Added in 7.31.0)
|
||||||
.IP CURLOPT_SSLCERTTYPE
|
.IP CURLOPT_SSLCERTTYPE
|
||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the format of your certificate. Supported formats are "PEM" and "DER". (Added
|
the format of your certificate. Supported formats are "PEM" and "DER". (Added
|
||||||
@@ -2216,6 +2274,10 @@ in 7.9.3)
|
|||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the file name of your private key. The default format is "PEM" and can be
|
the file name of your private key. The default format is "PEM" and can be
|
||||||
changed with \fICURLOPT_SSLKEYTYPE\fP.
|
changed with \fICURLOPT_SSLKEYTYPE\fP.
|
||||||
|
|
||||||
|
(iOS and Mac OS X only) This option is ignored if curl was built against Secure
|
||||||
|
Transport. Secure Transport expects the private key to be already present in
|
||||||
|
the keychain containing the certificate.
|
||||||
.IP CURLOPT_SSLKEYTYPE
|
.IP CURLOPT_SSLKEYTYPE
|
||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
.\" * | (__| |_| | _ <| |___
|
.\" * | (__| |_| | _ <| |___
|
||||||
.\" * \___|\___/|_| \_\_____|
|
.\" * \___|\___/|_| \_\_____|
|
||||||
.\" *
|
.\" *
|
||||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
.\" *
|
.\" *
|
||||||
.\" * This software is licensed as described in the file COPYING, which
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
@@ -42,7 +42,7 @@ After the \fIlastitem\fP pointer follow the real arguments.
|
|||||||
The pointers \fIfirstitem\fP and \fIlastitem\fP should both be pointing to
|
The pointers \fIfirstitem\fP and \fIlastitem\fP should both be pointing to
|
||||||
NULL in the first call to this function. All list-data will be allocated by
|
NULL in the first call to this function. All list-data will be allocated by
|
||||||
the function itself. You must call \fIcurl_formfree(3)\fP on the
|
the function itself. You must call \fIcurl_formfree(3)\fP on the
|
||||||
\fIfirstitem\P after the form post has been done to free the resources.
|
\fIfirstitem\fP after the form post has been done to free the resources.
|
||||||
|
|
||||||
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
|
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
|
||||||
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.
|
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ The socket \fBcallback\fP function uses a prototype like this
|
|||||||
int action, /* see values below */
|
int action, /* see values below */
|
||||||
void *userp, /* private callback pointer */
|
void *userp, /* private callback pointer */
|
||||||
void *socketp); /* private socket pointer,
|
void *socketp); /* private socket pointer,
|
||||||
\fBNULL\fI if not
|
\fBNULL\fP if not
|
||||||
previously assigned with
|
previously assigned with
|
||||||
\fIcurl_multi_assign(3)\fP */
|
\fBcurl_multi_assign(3)\fP */
|
||||||
|
|
||||||
.fi
|
.fi
|
||||||
The callback MUST return 0.
|
The callback MUST return 0.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
.\" * | (__| |_| | _ <| |___
|
.\" * | (__| |_| | _ <| |___
|
||||||
.\" * \___|\___/|_| \_\_____|
|
.\" * \___|\___/|_| \_\_____|
|
||||||
.\" *
|
.\" *
|
||||||
.\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
.\" *
|
.\" *
|
||||||
.\" * This software is licensed as described in the file COPYING, which
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
@@ -36,12 +36,17 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
|||||||
This function polls on all file descriptors used by the curl easy handles
|
This function polls on all file descriptors used by the curl easy handles
|
||||||
contained in the given multi handle set. It will block until activity is
|
contained in the given multi handle set. It will block until activity is
|
||||||
detected on at least one of the handles or \fItimeout_ms\fP has passed.
|
detected on at least one of the handles or \fItimeout_ms\fP has passed.
|
||||||
|
Alternatively, if the multi handle has a pending internal timeout that has a
|
||||||
|
shorter expiry time than \fItimeout_ms\fP, that shorter time will be used
|
||||||
|
instead to make sure timeout accuracy is reasonably kept.
|
||||||
|
|
||||||
The calling application may pass additional curl_waitfd structures which are
|
The calling application may pass additional curl_waitfd structures which are
|
||||||
similar to \fIpoll(2)\fP's pollfd structure to be waited on in the same call.
|
similar to \fIpoll(2)\fP's pollfd structure to be waited on in the same call.
|
||||||
|
|
||||||
On completion, if \fInumfds\fP is supplied, it will be populated with the
|
On completion, if \fInumfds\fP is supplied, it will be populated with the
|
||||||
number of file descriptors on which interesting events occured.
|
total number of file descriptors on which interesting events occured. This
|
||||||
|
number can include both libcurl internal descriptors as well as descriptors
|
||||||
|
provided in \fIextra_fds\fP.
|
||||||
|
|
||||||
If no extra file descriptors are provided and libcurl has no file descriptor
|
If no extra file descriptors are provided and libcurl has no file descriptor
|
||||||
to offer to wait for, this function will return immediately.
|
to offer to wait for, this function will return immediately.
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ The share interface was added to enable sharing of data between curl
|
|||||||
\&"handles".
|
\&"handles".
|
||||||
.SH "ONE SET OF DATA - MANY TRANSFERS"
|
.SH "ONE SET OF DATA - MANY TRANSFERS"
|
||||||
You can have multiple easy handles share data between them. Have them update
|
You can have multiple easy handles share data between them. Have them update
|
||||||
and use the \fBsame\fP cookie database or DNS cache! This way, each single
|
and use the \fBsame\fP cookie database, DNS cache, TLS session cache! This
|
||||||
transfer will take advantage from data updates made by the other transfer(s).
|
way, each single transfer will take advantage from data updates made by the
|
||||||
|
other transfer(s). The sharing interface, however, does not share active or
|
||||||
|
persistent connections between different easy handles.
|
||||||
.SH "SHARE OBJECT"
|
.SH "SHARE OBJECT"
|
||||||
You create a shared object with \fIcurl_share_init(3)\fP. It returns a handle
|
You create a shared object with \fIcurl_share_init(3)\fP. It returns a handle
|
||||||
for a newly created one.
|
for a newly created one.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
.\" * | (__| |_| | _ <| |___
|
.\" * | (__| |_| | _ <| |___
|
||||||
.\" * \___|\___/|_| \_\_____|
|
.\" * \___|\___/|_| \_\_____|
|
||||||
.\" *
|
.\" *
|
||||||
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
.\" *
|
.\" *
|
||||||
.\" * This software is licensed as described in the file COPYING, which
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
@@ -1157,13 +1157,13 @@ and install a CURLOPT_OPENSOCKETFUNCTION callback function in which addresses
|
|||||||
are sanitized before use.
|
are sanitized before use.
|
||||||
|
|
||||||
.IP "Private Resources"
|
.IP "Private Resources"
|
||||||
A user who can control the DNS server of a domain being passed in within
|
A user who can control the DNS server of a domain being passed in within a URL
|
||||||
a URL can change the address of the host to a local, private address
|
can change the address of the host to a local, private address which a
|
||||||
which the libcurl application will then use. e.g. The innocuous URL
|
server-side libcurl-using application could then use. e.g. the innocuous URL
|
||||||
http://fuzzybunnies.example.com/ could actually resolve to the IP address
|
http://fuzzybunnies.example.com/ could actually resolve to the IP address of a
|
||||||
of a server behind a firewall, such as 127.0.0.1 or 10.1.2.3
|
server behind a firewall, such as 127.0.0.1 or 10.1.2.3. Apps can mitigate
|
||||||
Apps can mitigate against this by setting a CURLOPT_OPENSOCKETFUNCTION
|
against this by setting a CURLOPT_OPENSOCKETFUNCTION and checking the address
|
||||||
and checking the address before a connection.
|
before a connection.
|
||||||
|
|
||||||
All the malicious scenarios regarding redirected URLs apply just as well
|
All the malicious scenarios regarding redirected URLs apply just as well
|
||||||
to non-redirected URLs, if the user is allowed to specify an arbitrary URL
|
to non-redirected URLs, if the user is allowed to specify an arbitrary URL
|
||||||
@@ -1178,6 +1178,19 @@ IP address and port number for a server local to the app running libcurl
|
|||||||
but behind a firewall. Apps can mitigate against this by using the
|
but behind a firewall. Apps can mitigate against this by using the
|
||||||
CURLOPT_FTP_SKIP_PASV_IP option or CURLOPT_FTPPORT.
|
CURLOPT_FTP_SKIP_PASV_IP option or CURLOPT_FTPPORT.
|
||||||
|
|
||||||
|
.IP "IPv6 Addresses"
|
||||||
|
libcurl will normally handle IPv6 addresses transparently and just as easily
|
||||||
|
as IPv4 addresses. That means that a sanitizing function that filters out
|
||||||
|
addressses like 127.0.0.1 isn't sufficient--the equivalent IPv6 addresses ::1,
|
||||||
|
::, 0:00::0:1, ::127.0.0.1 and ::ffff:7f00:1 supplied somehow by an attacker
|
||||||
|
would all bypass a naive filter and could allow access to undesired local
|
||||||
|
resources. IPv6 also has special address blocks like link-local and site-local
|
||||||
|
that generally shouldn't be accessed by a server-side libcurl-using
|
||||||
|
application. A poorly-configured firewall installed in a data center,
|
||||||
|
organization or server may also be configured to limit IPv4 connections but
|
||||||
|
leave IPv6 connections wide open. In some cases, the CURL_IPRESOLVE_V4 option
|
||||||
|
can be used to limit resolved addresses to IPv4 only and bypass these issues.
|
||||||
|
|
||||||
.IP Uploads
|
.IP Uploads
|
||||||
When uploading, a redirect can cause a local (or remote) file to be
|
When uploading, a redirect can cause a local (or remote) file to be
|
||||||
overwritten. Apps must not allow any unsanitized URL to be passed in
|
overwritten. Apps must not allow any unsanitized URL to be passed in
|
||||||
@@ -1250,7 +1263,7 @@ using the Content-disposition: header to generate a file name. An application
|
|||||||
could also use CURLINFO_EFFECTIVE_URL to generate a file name from a
|
could also use CURLINFO_EFFECTIVE_URL to generate a file name from a
|
||||||
server-supplied redirect URL. Special care must be taken to sanitize such
|
server-supplied redirect URL. Special care must be taken to sanitize such
|
||||||
names to avoid the possibility of a malicious server supplying one like
|
names to avoid the possibility of a malicious server supplying one like
|
||||||
"/etc/passwd", "\autoexec.bat" or even ".bashrc".
|
"/etc/passwd", "\\autoexec.bat", "prn:" or even ".bashrc".
|
||||||
|
|
||||||
.IP "Server Certificates"
|
.IP "Server Certificates"
|
||||||
A secure application should never use the CURLOPT_SSL_VERIFYPEER option to
|
A secure application should never use the CURLOPT_SSL_VERIFYPEER option to
|
||||||
@@ -1263,10 +1276,15 @@ validated certificates is potentially as insecure as a plain HTTP connection.
|
|||||||
On a related issue, be aware that even in situations like when you have
|
On a related issue, be aware that even in situations like when you have
|
||||||
problems with libcurl and ask someone for help, everything you reveal in order
|
problems with libcurl and ask someone for help, everything you reveal in order
|
||||||
to get best possible help might also impose certain security related
|
to get best possible help might also impose certain security related
|
||||||
risks. Host names, user names, paths, operating system specifics, etc (not to
|
risks. Host names, user names, paths, operating system specifics, etc. (not to
|
||||||
mention passwords of course) may in fact be used by intruders to gain
|
mention passwords of course) may in fact be used by intruders to gain
|
||||||
additional information of a potential target.
|
additional information of a potential target.
|
||||||
|
|
||||||
|
Be sure to limit access to application logs if they could hold private or
|
||||||
|
security-related data. Besides the obvious candidates like user names and
|
||||||
|
passwords, things like URLs, cookies or even file names could also hold
|
||||||
|
sensitive data.
|
||||||
|
|
||||||
To avoid this problem, you must of course use your common sense. Often, you
|
To avoid this problem, you must of course use your common sense. Often, you
|
||||||
can just edit out the sensitive data or just search/replace your true
|
can just edit out the sensitive data or just search/replace your true
|
||||||
information with faked data.
|
information with faked data.
|
||||||
@@ -1347,10 +1365,10 @@ automatically share a lot of the data that otherwise would be kept on a
|
|||||||
per-easy handle basis when the easy interface is used.
|
per-easy handle basis when the easy interface is used.
|
||||||
|
|
||||||
The DNS cache is shared between handles within a multi handle, making
|
The DNS cache is shared between handles within a multi handle, making
|
||||||
subsequent name resolvings faster and the connection pool that is kept to
|
subsequent name resolving faster, and the connection pool that is kept to
|
||||||
better allow persistent connections and connection re-use is shared. If you're
|
better allow persistent connections and connection re-use is also shared. If
|
||||||
using the easy interface, you can still share these between specific easy
|
you're using the easy interface, you can still share these between specific
|
||||||
handles by using the share interface, see \fIlibcurl-share(3)\fP.
|
easy handles by using the share interface, see \fIlibcurl-share(3)\fP.
|
||||||
|
|
||||||
Some things are never shared automatically, not within multi handles, like for
|
Some things are never shared automatically, not within multi handles, like for
|
||||||
example cookies so the only way to share that is with the share interface.
|
example cookies so the only way to share that is with the share interface.
|
||||||
|
|||||||
@@ -456,6 +456,7 @@ CURLOPT_RTSP_SERVER_CSEQ 7.20.0
|
|||||||
CURLOPT_RTSP_SESSION_ID 7.20.0
|
CURLOPT_RTSP_SESSION_ID 7.20.0
|
||||||
CURLOPT_RTSP_STREAM_URI 7.20.0
|
CURLOPT_RTSP_STREAM_URI 7.20.0
|
||||||
CURLOPT_RTSP_TRANSPORT 7.20.0
|
CURLOPT_RTSP_TRANSPORT 7.20.0
|
||||||
|
CURLOPT_SASL_IR 7.31.0
|
||||||
CURLOPT_SEEKDATA 7.18.0
|
CURLOPT_SEEKDATA 7.18.0
|
||||||
CURLOPT_SEEKFUNCTION 7.18.0
|
CURLOPT_SEEKFUNCTION 7.18.0
|
||||||
CURLOPT_SERVER_RESPONSE_TIMEOUT 7.20.0
|
CURLOPT_SERVER_RESPONSE_TIMEOUT 7.20.0
|
||||||
|
|||||||
@@ -1527,9 +1527,12 @@ typedef enum {
|
|||||||
/* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
|
/* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
|
||||||
CINIT(SSL_OPTIONS, LONG, 216),
|
CINIT(SSL_OPTIONS, LONG, 216),
|
||||||
|
|
||||||
/* set the SMTP auth originator */
|
/* Set the SMTP auth originator */
|
||||||
CINIT(MAIL_AUTH, OBJECTPOINT, 217),
|
CINIT(MAIL_AUTH, OBJECTPOINT, 217),
|
||||||
|
|
||||||
|
/* Enable/disable SASL initial response */
|
||||||
|
CINIT(SASL_IR, LONG, 218),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unused */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,12 @@
|
|||||||
|
|
||||||
/* This is the version number of the libcurl package from which this header
|
/* This is the version number of the libcurl package from which this header
|
||||||
file origins: */
|
file origins: */
|
||||||
#define LIBCURL_VERSION "7.30.0-DEV"
|
#define LIBCURL_VERSION "7.31.0-DEV"
|
||||||
|
|
||||||
/* The numeric version number is also available "in parts" by using these
|
/* The numeric version number is also available "in parts" by using these
|
||||||
defines: */
|
defines: */
|
||||||
#define LIBCURL_VERSION_MAJOR 7
|
#define LIBCURL_VERSION_MAJOR 7
|
||||||
#define LIBCURL_VERSION_MINOR 30
|
#define LIBCURL_VERSION_MINOR 31
|
||||||
#define LIBCURL_VERSION_PATCH 0
|
#define LIBCURL_VERSION_PATCH 0
|
||||||
|
|
||||||
/* This is the numeric version of the libcurl version number, meant for easier
|
/* This is the numeric version of the libcurl version number, meant for easier
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
and it is always a greater number in a more recent release. It makes
|
and it is always a greater number in a more recent release. It makes
|
||||||
comparisons with greater than and less than work.
|
comparisons with greater than and less than work.
|
||||||
*/
|
*/
|
||||||
#define LIBCURL_VERSION_NUM 0x071e00
|
#define LIBCURL_VERSION_NUM 0x071f00
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the date and time when the full source package was created. The
|
* This is the date and time when the full source package was created. The
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ CFLAGS += -dWANT_IDN_PROTOTYPES
|
|||||||
!ifdef %zlib_root
|
!ifdef %zlib_root
|
||||||
ZLIB_ROOT = $(%zlib_root)
|
ZLIB_ROOT = $(%zlib_root)
|
||||||
!else
|
!else
|
||||||
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.7
|
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.8
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
!ifdef %libssh2_root
|
!ifdef %libssh2_root
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ BCCDIR = $(MAKEDIR)\..
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
!ifndef ZLIB_PATH
|
!ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ..\..\zlib-1.2.7
|
ZLIB_PATH = ..\..\zlib-1.2.8
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
|
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-sspi-winidn
|
||||||
##
|
##
|
||||||
## Hint: you can also set environment vars to control the build, f.e.:
|
## Hint: you can also set environment vars to control the build, f.e.:
|
||||||
## set ZLIB_PATH=c:/zlib-1.2.7
|
## set ZLIB_PATH=c:/zlib-1.2.8
|
||||||
## set ZLIB=1
|
## set ZLIB=1
|
||||||
#
|
#
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
ifndef ZLIB_PATH
|
ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ../../zlib-1.2.7
|
ZLIB_PATH = ../../zlib-1.2.8
|
||||||
endif
|
endif
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ endif
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
ifndef ZLIB_PATH
|
ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ../../zlib-1.2.7
|
ZLIB_PATH = ../../zlib-1.2.8
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ LIBSSH2_PATH = ../../libssh2-1.4.3
|
|||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
!IFNDEF ZLIB_PATH
|
!IFNDEF ZLIB_PATH
|
||||||
ZLIB_PATH = ../../zlib-1.2.7
|
ZLIB_PATH = ../../zlib-1.2.8
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
!IFNDEF MACHINE
|
!IFNDEF MACHINE
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ USER_CFLAGS:=
|
|||||||
# directories where to seek for includes and libraries
|
# directories where to seek for includes and libraries
|
||||||
OPENSSL_INC := D:/libraries/openssl/openssl-0.9.8y-vxWorks6.3/include
|
OPENSSL_INC := D:/libraries/openssl/openssl-0.9.8y-vxWorks6.3/include
|
||||||
OPENSSL_LIB := D:/libraries/openssl/openssl-0.9.8y-vxWorks6.3
|
OPENSSL_LIB := D:/libraries/openssl/openssl-0.9.8y-vxWorks6.3
|
||||||
ZLIB_INC := D:/libraries/zlib/zlib-1.2.7-VxWorks6.3/zlib-1.2.7
|
ZLIB_INC := D:/libraries/zlib/zlib-1.2.8-VxWorks6.3/zlib-1.2.8
|
||||||
ZLIB_LIB := D:/libraries/zlib/zlib-1.2.7-VxWorks6.3/binaries/vxworks_3.1_gnu/Debug/lib
|
ZLIB_LIB := D:/libraries/zlib/zlib-1.2.8-VxWorks6.3/binaries/vxworks_3.1_gnu/Debug/lib
|
||||||
ARES_INC :=
|
ARES_INC :=
|
||||||
ARES_LIB :=
|
ARES_LIB :=
|
||||||
|
|
||||||
|
|||||||
256
lib/axtls.c
256
lib/axtls.c
@@ -41,26 +41,12 @@
|
|||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
|
#include <unistd.h>
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#include "hostcheck.h"
|
#include "hostcheck.h"
|
||||||
|
|
||||||
|
|
||||||
/* SSL_read is opied from axTLS compat layer */
|
|
||||||
static int SSL_read(SSL *ssl, void *buf, int num)
|
|
||||||
{
|
|
||||||
uint8_t *read_buf;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
while((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
|
|
||||||
|
|
||||||
if(ret > SSL_OK) {
|
|
||||||
memcpy(buf, read_buf, ret > num ? num : ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Global axTLS init, called from Curl_ssl_init() */
|
/* Global axTLS init, called from Curl_ssl_init() */
|
||||||
int Curl_axtls_init(void)
|
int Curl_axtls_init(void)
|
||||||
{
|
{
|
||||||
@@ -131,31 +117,40 @@ static CURLcode map_error_to_curl(int axtls_err)
|
|||||||
static Curl_recv axtls_recv;
|
static Curl_recv axtls_recv;
|
||||||
static Curl_send axtls_send;
|
static Curl_send axtls_send;
|
||||||
|
|
||||||
/*
|
static void free_ssl_structs(struct ssl_connect_data *connssl)
|
||||||
* This function is called after the TCP connect has completed. Setup the TLS
|
{
|
||||||
* layer and do all necessary magic.
|
if(connssl->ssl) {
|
||||||
*/
|
ssl_free (connssl->ssl);
|
||||||
CURLcode
|
connssl->ssl = NULL;
|
||||||
Curl_axtls_connect(struct connectdata *conn,
|
}
|
||||||
int sockindex)
|
if(connssl->ssl_ctx) {
|
||||||
|
ssl_ctx_free(connssl->ssl_ctx);
|
||||||
|
connssl->ssl_ctx = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For both blocking and non-blocking connects, this function sets up the
|
||||||
|
* ssl context and state. This function is called after the TCP connect
|
||||||
|
* has completed.
|
||||||
|
*/
|
||||||
|
static CURLcode connect_prep(struct connectdata *conn, int sockindex)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
SSL *ssl;
|
SSL *ssl = NULL;
|
||||||
int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
|
int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
|
||||||
int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
|
int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
|
||||||
int i, ssl_fcn_return;
|
int i, ssl_fcn_return;
|
||||||
const uint8_t *ssl_sessionid;
|
const uint8_t *ssl_sessionid;
|
||||||
size_t ssl_idsize;
|
size_t ssl_idsize;
|
||||||
const char *peer_CN;
|
|
||||||
uint32_t dns_altname_index;
|
|
||||||
const char *dns_altname;
|
|
||||||
int8_t found_subject_alt_names = 0;
|
|
||||||
int8_t found_subject_alt_name_matching_conn = 0;
|
|
||||||
|
|
||||||
/* Assuming users will not compile in custom key/cert to axTLS */
|
/* Assuming users will not compile in custom key/cert to axTLS.
|
||||||
uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER;
|
* Also, even for blocking connects, use axTLS non-blocking feature.
|
||||||
|
*/
|
||||||
|
uint32_t client_option = SSL_NO_DEFAULT_KEY |
|
||||||
|
SSL_SERVER_VERIFY_LATER |
|
||||||
|
SSL_CONNECT_IN_PARTS;
|
||||||
|
|
||||||
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
||||||
/* to make us tolerant against being called more than once for the
|
/* to make us tolerant against being called more than once for the
|
||||||
@@ -184,6 +179,9 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn->ssl[sockindex].ssl_ctx = ssl_ctx;
|
||||||
|
conn->ssl[sockindex].ssl = NULL;
|
||||||
|
|
||||||
/* Load the trusted CA cert bundle file */
|
/* Load the trusted CA cert bundle file */
|
||||||
if(data->set.ssl.CAfile) {
|
if(data->set.ssl.CAfile) {
|
||||||
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
|
if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
|
||||||
@@ -191,7 +189,6 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
infof(data, "error reading ca cert file %s \n",
|
infof(data, "error reading ca cert file %s \n",
|
||||||
data->set.ssl.CAfile);
|
data->set.ssl.CAfile);
|
||||||
if(data->set.ssl.verifypeer) {
|
if(data->set.ssl.verifypeer) {
|
||||||
Curl_axtls_close(conn, sockindex);
|
|
||||||
return CURLE_SSL_CACERT_BADFILE;
|
return CURLE_SSL_CACERT_BADFILE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +222,6 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
if(cert_types[i] == 0) {
|
if(cert_types[i] == 0) {
|
||||||
failf(data, "%s is not x509 or pkcs12 format",
|
failf(data, "%s is not x509 or pkcs12 format",
|
||||||
data->set.str[STRING_CERT]);
|
data->set.str[STRING_CERT]);
|
||||||
Curl_axtls_close(conn, sockindex);
|
|
||||||
return CURLE_SSL_CERTPROBLEM;
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +246,6 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
if(key_types[i] == 0) {
|
if(key_types[i] == 0) {
|
||||||
failf(data, "Failure: %s is not a supported key file",
|
failf(data, "Failure: %s is not a supported key file",
|
||||||
data->set.str[STRING_KEY]);
|
data->set.str[STRING_KEY]);
|
||||||
Curl_axtls_close(conn, sockindex);
|
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,14 +266,25 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
else
|
else
|
||||||
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
|
ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
|
||||||
|
|
||||||
/* Check to make sure handshake was ok. */
|
conn->ssl[sockindex].ssl = ssl;
|
||||||
ssl_fcn_return = ssl_handshake_status(ssl);
|
return CURLE_OK;
|
||||||
if(ssl_fcn_return != SSL_OK) {
|
}
|
||||||
Curl_axtls_close(conn, sockindex);
|
|
||||||
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
|
/*
|
||||||
return map_error_to_curl(ssl_fcn_return);
|
* For both blocking and non-blocking connects, this function finalizes the
|
||||||
}
|
* SSL connection.
|
||||||
infof (data, "handshake completed successfully\n");
|
*/
|
||||||
|
static CURLcode connect_finish(struct connectdata *conn, int sockindex)
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
SSL *ssl = conn->ssl[sockindex].ssl;
|
||||||
|
const uint8_t *ssl_sessionid;
|
||||||
|
size_t ssl_idsize;
|
||||||
|
const char *peer_CN;
|
||||||
|
uint32_t dns_altname_index;
|
||||||
|
const char *dns_altname;
|
||||||
|
int8_t found_subject_alt_names = 0;
|
||||||
|
int8_t found_subject_alt_name_matching_conn = 0;
|
||||||
|
|
||||||
/* Here, gtls.c gets the peer certificates and fails out depending on
|
/* Here, gtls.c gets the peer certificates and fails out depending on
|
||||||
* settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
|
* settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
|
||||||
@@ -289,7 +295,7 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
if(ssl_verify_cert(ssl) != SSL_OK) {
|
if(ssl_verify_cert(ssl) != SSL_OK) {
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "server cert verify failed");
|
failf(data, "server cert verify failed");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -306,7 +312,6 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
* this, but a couple fields are available.
|
* this, but a couple fields are available.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
|
/* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
|
||||||
risk of an inifite loop */
|
risk of an inifite loop */
|
||||||
for(dns_altname_index = 0; ; dns_altname_index++) {
|
for(dns_altname_index = 0; ; dns_altname_index++) {
|
||||||
@@ -326,21 +331,30 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
|
|
||||||
/* RFC2818 checks */
|
/* RFC2818 checks */
|
||||||
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
|
if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
|
||||||
|
if(data->set.ssl.verifyhost) {
|
||||||
/* Break connection ! */
|
/* Break connection ! */
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname);
|
failf(data, "\tsubjectAltName(s) do not match %s\n",
|
||||||
|
conn->host.dispname);
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
infof(data, "\tsubjectAltName(s) do not match %s\n",
|
||||||
|
conn->host.dispname);
|
||||||
|
}
|
||||||
else if(found_subject_alt_names == 0) {
|
else if(found_subject_alt_names == 0) {
|
||||||
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
|
/* Per RFC2818, when no Subject Alt Names were available, examine the peer
|
||||||
CN as a legacy fallback */
|
CN as a legacy fallback */
|
||||||
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
|
peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
|
||||||
if(peer_CN == NULL) {
|
if(peer_CN == NULL) {
|
||||||
/* Similar behaviour to the OpenSSL interface */
|
if(data->set.ssl.verifyhost) {
|
||||||
Curl_axtls_close(conn, sockindex);
|
Curl_axtls_close(conn, sockindex);
|
||||||
failf(data, "unable to obtain common name from peer certificate");
|
failf(data, "unable to obtain common name from peer certificate");
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
infof(data, "unable to obtain common name from peer certificate");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
|
if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
|
||||||
if(data->set.ssl.verifyhost) {
|
if(data->set.ssl.verifyhost) {
|
||||||
@@ -359,8 +373,6 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
|
|
||||||
/* General housekeeping */
|
/* General housekeeping */
|
||||||
conn->ssl[sockindex].state = ssl_connection_complete;
|
conn->ssl[sockindex].state = ssl_connection_complete;
|
||||||
conn->ssl[sockindex].ssl = ssl;
|
|
||||||
conn->ssl[sockindex].ssl_ctx = ssl_ctx;
|
|
||||||
conn->recv[sockindex] = axtls_recv;
|
conn->recv[sockindex] = axtls_recv;
|
||||||
conn->send[sockindex] = axtls_send;
|
conn->send[sockindex] = axtls_send;
|
||||||
|
|
||||||
@@ -374,6 +386,107 @@ Curl_axtls_connect(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use axTLS's non-blocking connection feature to open an SSL connection.
|
||||||
|
* This is called after a TCP connection is already established.
|
||||||
|
*/
|
||||||
|
CURLcode Curl_axtls_connect_nonblocking(
|
||||||
|
struct connectdata *conn,
|
||||||
|
int sockindex,
|
||||||
|
bool *done)
|
||||||
|
{
|
||||||
|
CURLcode conn_step;
|
||||||
|
int ssl_fcn_return;
|
||||||
|
|
||||||
|
*done = FALSE;
|
||||||
|
/* connectdata is calloc'd and connecting_state is only changed in this
|
||||||
|
function, so this is safe, as the state is effectively initialized. */
|
||||||
|
if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
|
||||||
|
conn_step = connect_prep(conn, sockindex);
|
||||||
|
if(conn_step != CURLE_OK) {
|
||||||
|
Curl_axtls_close(conn, sockindex);
|
||||||
|
return conn_step;
|
||||||
|
}
|
||||||
|
conn->ssl[sockindex].connecting_state = ssl_connect_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
|
||||||
|
/* Check to make sure handshake was ok. */
|
||||||
|
if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
|
||||||
|
ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
|
||||||
|
if(ssl_fcn_return < 0) {
|
||||||
|
Curl_axtls_close(conn, sockindex);
|
||||||
|
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
|
||||||
|
return map_error_to_curl(ssl_fcn_return);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CURLE_OK; /* Return control to caller for retries */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
infof (conn->data, "handshake completed successfully\n");
|
||||||
|
conn->ssl[sockindex].connecting_state = ssl_connect_3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
|
||||||
|
conn_step = connect_finish(conn, sockindex);
|
||||||
|
if(conn_step != CURLE_OK) {
|
||||||
|
Curl_axtls_close(conn, sockindex);
|
||||||
|
return conn_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset connect state */
|
||||||
|
conn->ssl[sockindex].connecting_state = ssl_connect_1;
|
||||||
|
|
||||||
|
*done = TRUE;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unrecognized state. Things are very bad. */
|
||||||
|
conn->ssl[sockindex].state = ssl_connection_none;
|
||||||
|
conn->ssl[sockindex].connecting_state = ssl_connect_1;
|
||||||
|
/* Return value perhaps not strictly correct, but distinguishes the issue.*/
|
||||||
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called after the TCP connect has completed. Setup the TLS
|
||||||
|
* layer and do all necessary magic for a blocking connect.
|
||||||
|
*/
|
||||||
|
CURLcode
|
||||||
|
Curl_axtls_connect(struct connectdata *conn,
|
||||||
|
int sockindex)
|
||||||
|
|
||||||
|
{
|
||||||
|
CURLcode conn_step = connect_prep(conn, sockindex);
|
||||||
|
int ssl_fcn_return;
|
||||||
|
SSL *ssl = conn->ssl[sockindex].ssl;
|
||||||
|
|
||||||
|
if(conn_step != CURLE_OK) {
|
||||||
|
Curl_axtls_close(conn, sockindex);
|
||||||
|
return conn_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check to make sure handshake was ok. */
|
||||||
|
while(ssl_handshake_status(ssl) != SSL_OK) {
|
||||||
|
ssl_fcn_return = ssl_read(ssl, NULL);
|
||||||
|
if(ssl_fcn_return < 0) {
|
||||||
|
Curl_axtls_close(conn, sockindex);
|
||||||
|
ssl_display_error(ssl_fcn_return); /* goes to stdout. */
|
||||||
|
return map_error_to_curl(ssl_fcn_return);
|
||||||
|
}
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
infof (conn->data, "handshake completed successfully\n");
|
||||||
|
|
||||||
|
conn_step = connect_finish(conn, sockindex);
|
||||||
|
if(conn_step != CURLE_OK) {
|
||||||
|
Curl_axtls_close(conn, sockindex);
|
||||||
|
return conn_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* return number of sent (non-SSL) bytes */
|
/* return number of sent (non-SSL) bytes */
|
||||||
static ssize_t axtls_send(struct connectdata *conn,
|
static ssize_t axtls_send(struct connectdata *conn,
|
||||||
@@ -407,7 +520,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex)
|
|||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
|
|
||||||
infof(conn->data, " Curl_axtls_close\n");
|
infof(conn->data, " Curl_axtls_close\n");
|
||||||
if(connssl->ssl) {
|
|
||||||
/* line from ssluse.c: (void)SSL_shutdown(connssl->ssl);
|
/* line from ssluse.c: (void)SSL_shutdown(connssl->ssl);
|
||||||
axTLS compat layer does nothing for SSL_shutdown */
|
axTLS compat layer does nothing for SSL_shutdown */
|
||||||
|
|
||||||
@@ -415,13 +528,7 @@ void Curl_axtls_close(struct connectdata *conn, int sockindex)
|
|||||||
equivalent. ssl_free and ssl_ctx_free close things.
|
equivalent. ssl_free and ssl_ctx_free close things.
|
||||||
SSL_set_connect_state(connssl->handle); */
|
SSL_set_connect_state(connssl->handle); */
|
||||||
|
|
||||||
ssl_free (connssl->ssl);
|
free_ssl_structs(connssl);
|
||||||
connssl->ssl = NULL;
|
|
||||||
}
|
|
||||||
if(connssl->ssl_ctx) {
|
|
||||||
ssl_ctx_free (connssl->ssl_ctx);
|
|
||||||
connssl->ssl_ctx = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -436,8 +543,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
|
uint8_t *buf;
|
||||||
to be at least 120 bytes long. */
|
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
|
|
||||||
infof(conn->data, " Curl_axtls_shutdown\n");
|
infof(conn->data, " Curl_axtls_shutdown\n");
|
||||||
@@ -457,9 +563,10 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
|
||||||
if(what > 0) {
|
if(what > 0) {
|
||||||
/* Something to read, let's do it and hope that it is the close
|
/* Something to read, let's do it and hope that it is the close
|
||||||
notify alert from the server */
|
notify alert from the server. buf is managed internally by
|
||||||
nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf,
|
axTLS and will be released upon calling ssl_free via
|
||||||
sizeof(buf));
|
free_ssl_structs. */
|
||||||
|
nread = (ssize_t)ssl_read(connssl->ssl, &buf);
|
||||||
|
|
||||||
if(nread < SSL_OK) {
|
if(nread < SSL_OK) {
|
||||||
failf(data, "close notify alert not received during shutdown");
|
failf(data, "close notify alert not received during shutdown");
|
||||||
@@ -476,8 +583,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_free (connssl->ssl);
|
free_ssl_structs(connssl);
|
||||||
connssl->ssl = NULL;
|
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -490,26 +596,36 @@ static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
|
|||||||
{
|
{
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[num];
|
struct ssl_connect_data *connssl = &conn->ssl[num];
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
uint8_t *read_buf;
|
||||||
|
|
||||||
infof(conn->data, " axtls_recv\n");
|
infof(conn->data, " axtls_recv\n");
|
||||||
|
|
||||||
|
*err = CURLE_OK;
|
||||||
if(connssl) {
|
if(connssl) {
|
||||||
ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize);
|
ret = ssl_read(connssl->ssl, &read_buf);
|
||||||
|
if(ret > SSL_OK) {
|
||||||
/* axTLS isn't terribly generous about error reporting */
|
/* ssl_read returns SSL_OK if there is more data to read, so if it is
|
||||||
|
larger, then all data has been read already. */
|
||||||
|
memcpy(buf, read_buf,
|
||||||
|
(size_t)ret > buffersize ? buffersize : (size_t)ret);
|
||||||
|
}
|
||||||
|
else if(ret == SSL_OK) {
|
||||||
|
/* more data to be read, signal caller to call again */
|
||||||
|
*err = CURLE_AGAIN;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else if(ret == -3) {
|
||||||
/* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
|
/* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
|
||||||
team approves proposed fix. */
|
team approves proposed fix. */
|
||||||
if(ret == -3 ) {
|
|
||||||
Curl_axtls_close(conn, num);
|
Curl_axtls_close(conn, num);
|
||||||
}
|
}
|
||||||
else if(ret < 0) {
|
else {
|
||||||
failf(conn->data, "axTLS recv error (%d)", (int)ret);
|
failf(conn->data, "axTLS recv error (%d)", ret);
|
||||||
*err = map_error_to_curl(ret);
|
*err = map_error_to_curl(ret);
|
||||||
return -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*err = CURLE_OK;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,10 @@
|
|||||||
int Curl_axtls_init(void);
|
int Curl_axtls_init(void);
|
||||||
int Curl_axtls_cleanup(void);
|
int Curl_axtls_cleanup(void);
|
||||||
CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
|
CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
|
||||||
|
CURLcode Curl_axtls_connect_nonblocking(
|
||||||
|
struct connectdata *conn,
|
||||||
|
int sockindex,
|
||||||
|
bool *done);
|
||||||
|
|
||||||
/* tell axTLS to close down all open information regarding connections (and
|
/* tell axTLS to close down all open information regarding connections (and
|
||||||
thus session ID caching etc) */
|
thus session ID caching etc) */
|
||||||
@@ -47,6 +51,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn);
|
|||||||
#define curlssl_init Curl_axtls_init
|
#define curlssl_init Curl_axtls_init
|
||||||
#define curlssl_cleanup Curl_axtls_cleanup
|
#define curlssl_cleanup Curl_axtls_cleanup
|
||||||
#define curlssl_connect Curl_axtls_connect
|
#define curlssl_connect Curl_axtls_connect
|
||||||
|
#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking
|
||||||
#define curlssl_session_free(x) Curl_axtls_session_free(x)
|
#define curlssl_session_free(x) Curl_axtls_session_free(x)
|
||||||
#define curlssl_close_all Curl_axtls_close_all
|
#define curlssl_close_all Curl_axtls_close_all
|
||||||
#define curlssl_close Curl_axtls_close
|
#define curlssl_close Curl_axtls_close
|
||||||
|
|||||||
@@ -38,8 +38,6 @@
|
|||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
#define CONNECTION_HASH_SIZE 97
|
|
||||||
|
|
||||||
static void free_bundle_hash_entry(void *freethis)
|
static void free_bundle_hash_entry(void *freethis)
|
||||||
{
|
{
|
||||||
struct connectbundle *b = (struct connectbundle *) freethis;
|
struct connectbundle *b = (struct connectbundle *) freethis;
|
||||||
@@ -47,7 +45,7 @@ static void free_bundle_hash_entry(void *freethis)
|
|||||||
Curl_bundle_destroy(b);
|
Curl_bundle_destroy(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct conncache *Curl_conncache_init(void)
|
struct conncache *Curl_conncache_init(int size)
|
||||||
{
|
{
|
||||||
struct conncache *connc;
|
struct conncache *connc;
|
||||||
|
|
||||||
@@ -55,7 +53,7 @@ struct conncache *Curl_conncache_init(void)
|
|||||||
if(!connc)
|
if(!connc)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
connc->hash = Curl_hash_alloc(CONNECTION_HASH_SIZE, Curl_hash_str,
|
connc->hash = Curl_hash_alloc(size, Curl_hash_str,
|
||||||
Curl_str_key_compare, free_bundle_hash_entry);
|
Curl_str_key_compare, free_bundle_hash_entry);
|
||||||
|
|
||||||
if(!connc->hash) {
|
if(!connc->hash) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ struct conncache {
|
|||||||
size_t num_connections;
|
size_t num_connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct conncache *Curl_conncache_init(void);
|
struct conncache *Curl_conncache_init(int size);
|
||||||
|
|
||||||
void Curl_conncache_destroy(struct conncache *connc);
|
void Curl_conncache_destroy(struct conncache *connc);
|
||||||
|
|
||||||
|
|||||||
@@ -413,22 +413,21 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
if(af == AF_INET6) {
|
if(af == AF_INET6) {
|
||||||
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||||
char *scope_ptr = strchr(myhost, '%');
|
char *scope_ptr = strchr(myhost, '%');
|
||||||
|
if(scope_ptr)
|
||||||
if(scope_ptr) *(scope_ptr++) = 0;
|
*(scope_ptr++) = 0;
|
||||||
#endif
|
#endif
|
||||||
if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
|
if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
|
||||||
si6->sin6_family = AF_INET6;
|
si6->sin6_family = AF_INET6;
|
||||||
si6->sin6_port = htons(port);
|
si6->sin6_port = htons(port);
|
||||||
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||||
if(scope_ptr) {
|
if(scope_ptr)
|
||||||
/* The "myhost" string either comes from Curl_if2ip or
|
/* The "myhost" string either comes from Curl_if2ip or from
|
||||||
from Curl_printable_address. The latter returns only
|
Curl_printable_address. The latter returns only numeric scope
|
||||||
numeric scope IDs and the former returns none at all.
|
IDs and the former returns none at all. So the scope ID, if
|
||||||
So the scope ID, if present, is known to be numeric */
|
present, is known to be numeric */
|
||||||
si6->sin6_scope_id = atoi(scope_ptr);
|
si6->sin6_scope_id = atoi(scope_ptr);
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
sizeof_sa = sizeof(struct sockaddr_in6);
|
sizeof_sa = sizeof(struct sockaddr_in6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1252,7 +1251,13 @@ int Curl_closesocket(struct connectdata *conn,
|
|||||||
else
|
else
|
||||||
return conn->fclosesocket(conn->closesocket_client, sock);
|
return conn->fclosesocket(conn->closesocket_client, sock);
|
||||||
}
|
}
|
||||||
return sclose(sock);
|
sclose(sock);
|
||||||
|
|
||||||
|
if(conn)
|
||||||
|
/* tell the multi-socket code about this */
|
||||||
|
Curl_multi_closed(conn, sock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
189
lib/cookie.c
189
lib/cookie.c
@@ -106,6 +106,8 @@ static void freecookie(struct Cookie *co)
|
|||||||
free(co->domain);
|
free(co->domain);
|
||||||
if(co->path)
|
if(co->path)
|
||||||
free(co->path);
|
free(co->path);
|
||||||
|
if(co->spath)
|
||||||
|
free(co->spath);
|
||||||
if(co->name)
|
if(co->name)
|
||||||
free(co->name);
|
free(co->name);
|
||||||
if(co->value)
|
if(co->value)
|
||||||
@@ -143,6 +145,116 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* matching cookie path and url path
|
||||||
|
* RFC6265 5.1.4 Paths and Path-Match
|
||||||
|
*/
|
||||||
|
static bool pathmatch(const char* cookie_path, const char* request_uri)
|
||||||
|
{
|
||||||
|
size_t cookie_path_len;
|
||||||
|
size_t uri_path_len;
|
||||||
|
char* uri_path = NULL;
|
||||||
|
char* pos;
|
||||||
|
bool ret = FALSE;
|
||||||
|
|
||||||
|
/* cookie_path must not have last '/' separator. ex: /sample */
|
||||||
|
cookie_path_len = strlen(cookie_path);
|
||||||
|
if(1 == cookie_path_len) {
|
||||||
|
/* cookie_path must be '/' */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uri_path = strdup(request_uri);
|
||||||
|
if(!uri_path)
|
||||||
|
return FALSE;
|
||||||
|
pos = strchr(uri_path, '?');
|
||||||
|
if(pos)
|
||||||
|
*pos = 0x0;
|
||||||
|
|
||||||
|
/* #-fragments are already cut off! */
|
||||||
|
if(0 == strlen(uri_path) || uri_path[0] != '/') {
|
||||||
|
free(uri_path);
|
||||||
|
uri_path = strdup("/");
|
||||||
|
if(!uri_path)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* here, RFC6265 5.1.4 says
|
||||||
|
4. Output the characters of the uri-path from the first character up
|
||||||
|
to, but not including, the right-most %x2F ("/").
|
||||||
|
but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
|
||||||
|
without redirect.
|
||||||
|
Ignore this algorithm because /hoge is uri path for this case
|
||||||
|
(uri path is not /).
|
||||||
|
*/
|
||||||
|
|
||||||
|
uri_path_len = strlen(uri_path);
|
||||||
|
|
||||||
|
if(uri_path_len < cookie_path_len) {
|
||||||
|
ret = FALSE;
|
||||||
|
goto pathmatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not using checkprefix() because matching should be case-sensitive */
|
||||||
|
if(strncmp(cookie_path, uri_path, cookie_path_len)) {
|
||||||
|
ret = FALSE;
|
||||||
|
goto pathmatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The cookie-path and the uri-path are identical. */
|
||||||
|
if(cookie_path_len == uri_path_len) {
|
||||||
|
ret = TRUE;
|
||||||
|
goto pathmatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* here, cookie_path_len < url_path_len */
|
||||||
|
if(uri_path[cookie_path_len] == '/') {
|
||||||
|
ret = TRUE;
|
||||||
|
goto pathmatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
pathmatched:
|
||||||
|
free(uri_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cookie path sanitize
|
||||||
|
*/
|
||||||
|
static char *sanitize_cookie_path(const char *cookie_path)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *new_path = strdup(cookie_path);
|
||||||
|
if(!new_path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* some stupid site sends path attribute with '"'. */
|
||||||
|
if(new_path[0] == '\"') {
|
||||||
|
memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path));
|
||||||
|
}
|
||||||
|
if(new_path[strlen(new_path) - 1] == '\"') {
|
||||||
|
new_path[strlen(new_path) - 1] = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RFC6265 5.2.4 The Path Attribute */
|
||||||
|
if(new_path[0] != '/') {
|
||||||
|
/* Let cookie-path be the default-path. */
|
||||||
|
free(new_path);
|
||||||
|
new_path = strdup("/");
|
||||||
|
return new_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert /hoge/ to /hoge */
|
||||||
|
len = strlen(new_path);
|
||||||
|
if(1 < len && new_path[len - 1] == '/') {
|
||||||
|
new_path[len - 1] = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_path;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
|
* Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
|
||||||
*/
|
*/
|
||||||
@@ -184,6 +296,9 @@ static void strstore(char **str, const char *newstr)
|
|||||||
*
|
*
|
||||||
* Add a single cookie line to the cookie keeping object.
|
* Add a single cookie line to the cookie keeping object.
|
||||||
*
|
*
|
||||||
|
* Be aware that sometimes we get an IP-only host name, and that might also be
|
||||||
|
* a numerical IPv6 address.
|
||||||
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
struct Cookie *
|
struct Cookie *
|
||||||
@@ -288,45 +403,13 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
badcookie = TRUE; /* out of memory bad */
|
badcookie = TRUE; /* out of memory bad */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
co->spath = sanitize_cookie_path(co->path);
|
||||||
|
if(!co->spath) {
|
||||||
|
badcookie = TRUE; /* out of memory bad */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(Curl_raw_equal("domain", name)) {
|
else if(Curl_raw_equal("domain", name)) {
|
||||||
/* note that this name may or may not have a preceding dot, but
|
|
||||||
we don't care about that, we treat the names the same anyway */
|
|
||||||
|
|
||||||
const char *domptr=whatptr;
|
|
||||||
const char *nextptr;
|
|
||||||
int dotcount=1;
|
|
||||||
|
|
||||||
/* Count the dots, we need to make sure that there are enough
|
|
||||||
of them. */
|
|
||||||
|
|
||||||
if('.' == whatptr[0])
|
|
||||||
/* don't count the initial dot, assume it */
|
|
||||||
domptr++;
|
|
||||||
|
|
||||||
do {
|
|
||||||
nextptr = strchr(domptr, '.');
|
|
||||||
if(nextptr) {
|
|
||||||
if(domptr != nextptr)
|
|
||||||
dotcount++;
|
|
||||||
domptr = nextptr+1;
|
|
||||||
}
|
|
||||||
} while(nextptr);
|
|
||||||
|
|
||||||
/* The original Netscape cookie spec defined that this domain name
|
|
||||||
MUST have three dots (or two if one of the seven holy TLDs),
|
|
||||||
but it seems that these kinds of cookies are in use "out there"
|
|
||||||
so we cannot be that strict. I've therefore lowered the check
|
|
||||||
to not allow less than two dots. */
|
|
||||||
|
|
||||||
if(dotcount < 2) {
|
|
||||||
/* Received and skipped a cookie with a domain using too few
|
|
||||||
dots. */
|
|
||||||
badcookie=TRUE; /* mark this as a bad cookie */
|
|
||||||
infof(data, "skipped cookie with illegal dotcount domain: %s\n",
|
|
||||||
whatptr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Now, we make sure that our host is within the given domain,
|
/* Now, we make sure that our host is within the given domain,
|
||||||
or the given domain is not valid and thus cannot be set. */
|
or the given domain is not valid and thus cannot be set. */
|
||||||
|
|
||||||
@@ -355,7 +438,6 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
whatptr);
|
whatptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if(Curl_raw_equal("version", name)) {
|
else if(Curl_raw_equal("version", name)) {
|
||||||
strstore(&co->version, whatptr);
|
strstore(&co->version, whatptr);
|
||||||
if(!co->version) {
|
if(!co->version) {
|
||||||
@@ -461,6 +543,9 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
if(co->path) {
|
if(co->path) {
|
||||||
memcpy(co->path, path, pathlen);
|
memcpy(co->path, path, pathlen);
|
||||||
co->path[pathlen]=0; /* zero terminate */
|
co->path[pathlen]=0; /* zero terminate */
|
||||||
|
co->spath = sanitize_cookie_path(co->path);
|
||||||
|
if(!co->spath)
|
||||||
|
badcookie = TRUE; /* out of memory bad */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
badcookie = TRUE;
|
badcookie = TRUE;
|
||||||
@@ -512,12 +597,6 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
|
|
||||||
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
|
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
|
||||||
|
|
||||||
/* Here's a quick check to eliminate normal HTTP-headers from this */
|
|
||||||
if(!firstptr || strchr(firstptr, ':')) {
|
|
||||||
free(co);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now loop through the fields and init the struct we already have
|
/* Now loop through the fields and init the struct we already have
|
||||||
allocated */
|
allocated */
|
||||||
for(ptr=firstptr, fields=0; ptr && !badcookie;
|
for(ptr=firstptr, fields=0; ptr && !badcookie;
|
||||||
@@ -552,12 +631,21 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
co->path = strdup(ptr);
|
co->path = strdup(ptr);
|
||||||
if(!co->path)
|
if(!co->path)
|
||||||
badcookie = TRUE;
|
badcookie = TRUE;
|
||||||
|
else {
|
||||||
|
co->spath = sanitize_cookie_path(co->path);
|
||||||
|
if(!co->spath) {
|
||||||
|
badcookie = TRUE; /* out of memory bad */
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* this doesn't look like a path, make one up! */
|
/* this doesn't look like a path, make one up! */
|
||||||
co->path = strdup("/");
|
co->path = strdup("/");
|
||||||
if(!co->path)
|
if(!co->path)
|
||||||
badcookie = TRUE;
|
badcookie = TRUE;
|
||||||
|
co->spath = strdup("/");
|
||||||
|
if(!co->spath)
|
||||||
|
badcookie = TRUE;
|
||||||
fields++; /* add a field and fall down to secure */
|
fields++; /* add a field and fall down to secure */
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 3:
|
case 3:
|
||||||
@@ -628,14 +716,14 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
if(replace_old) {
|
if(replace_old) {
|
||||||
/* the domains were identical */
|
/* the domains were identical */
|
||||||
|
|
||||||
if(clist->path && co->path) {
|
if(clist->spath && co->spath) {
|
||||||
if(Curl_raw_equal(clist->path, co->path)) {
|
if(Curl_raw_equal(clist->spath, co->spath)) {
|
||||||
replace_old = TRUE;
|
replace_old = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
replace_old = FALSE;
|
replace_old = FALSE;
|
||||||
}
|
}
|
||||||
else if(!clist->path && !co->path)
|
else if(!clist->spath && !co->spath)
|
||||||
replace_old = TRUE;
|
replace_old = TRUE;
|
||||||
else
|
else
|
||||||
replace_old = FALSE;
|
replace_old = FALSE;
|
||||||
@@ -664,6 +752,8 @@ Curl_cookie_add(struct SessionHandle *data,
|
|||||||
free(clist->domain);
|
free(clist->domain);
|
||||||
if(clist->path)
|
if(clist->path)
|
||||||
free(clist->path);
|
free(clist->path);
|
||||||
|
if(clist->spath)
|
||||||
|
free(clist->spath);
|
||||||
if(clist->expirestr)
|
if(clist->expirestr)
|
||||||
free(clist->expirestr);
|
free(clist->expirestr);
|
||||||
|
|
||||||
@@ -858,10 +948,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|||||||
|
|
||||||
/* now check the left part of the path with the cookies path
|
/* now check the left part of the path with the cookies path
|
||||||
requirement */
|
requirement */
|
||||||
if(!co->path ||
|
if(!co->spath || pathmatch(co->spath, path) ) {
|
||||||
/* not using checkprefix() because matching should be
|
|
||||||
case-sensitive */
|
|
||||||
!strncmp(co->path, path, strlen(co->path)) ) {
|
|
||||||
|
|
||||||
/* and now, we know this is a match and we should create an
|
/* and now, we know this is a match and we should create an
|
||||||
entry for the return-linked-list */
|
entry for the return-linked-list */
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ struct Cookie {
|
|||||||
struct Cookie *next; /* next in the chain */
|
struct Cookie *next; /* next in the chain */
|
||||||
char *name; /* <this> = value */
|
char *name; /* <this> = value */
|
||||||
char *value; /* name = <this> */
|
char *value; /* name = <this> */
|
||||||
char *path; /* path = <this> */
|
char *path; /* path = <this> which is in Set-Cookie: */
|
||||||
|
char *spath; /* sanitized cookie path */
|
||||||
char *domain; /* domain = <this> */
|
char *domain; /* domain = <this> */
|
||||||
curl_off_t expires; /* expires = <this> */
|
curl_off_t expires; /* expires = <this> */
|
||||||
char *expirestr; /* the plain text version */
|
char *expirestr; /* the plain text version */
|
||||||
|
|||||||
@@ -691,6 +691,101 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
|
|||||||
return server_cert_summary;
|
return server_cert_summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||||
|
static OSStatus CopyIdentityWithLabelOldSchool(char *label,
|
||||||
|
SecIdentityRef *out_c_a_k)
|
||||||
|
{
|
||||||
|
OSStatus status = errSecItemNotFound;
|
||||||
|
/* The SecKeychainSearch API was deprecated in Lion, and using it will raise
|
||||||
|
deprecation warnings, so let's not compile this unless it's necessary: */
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
|
||||||
|
SecKeychainAttributeList attr_list;
|
||||||
|
SecKeychainAttribute attr;
|
||||||
|
SecKeychainSearchRef search = NULL;
|
||||||
|
SecCertificateRef cert = NULL;
|
||||||
|
|
||||||
|
/* Set up the attribute list: */
|
||||||
|
attr_list.count = 1L;
|
||||||
|
attr_list.attr = &attr;
|
||||||
|
|
||||||
|
/* Set up our lone search criterion: */
|
||||||
|
attr.tag = kSecLabelItemAttr;
|
||||||
|
attr.data = label;
|
||||||
|
attr.length = (UInt32)strlen(label);
|
||||||
|
|
||||||
|
/* Start searching: */
|
||||||
|
status = SecKeychainSearchCreateFromAttributes(NULL,
|
||||||
|
kSecCertificateItemClass,
|
||||||
|
&attr_list,
|
||||||
|
&search);
|
||||||
|
if(status == noErr) {
|
||||||
|
status = SecKeychainSearchCopyNext(search,
|
||||||
|
(SecKeychainItemRef *)&cert);
|
||||||
|
if(status == noErr && cert) {
|
||||||
|
/* If we found a certificate, does it have a private key? */
|
||||||
|
status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
|
||||||
|
CFRelease(cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(search)
|
||||||
|
CFRelease(search);
|
||||||
|
#else
|
||||||
|
#pragma unused(label, out_c_a_k)
|
||||||
|
#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 */
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||||
|
|
||||||
|
static OSStatus CopyIdentityWithLabel(char *label,
|
||||||
|
SecIdentityRef *out_cert_and_key)
|
||||||
|
{
|
||||||
|
OSStatus status = errSecItemNotFound;
|
||||||
|
|
||||||
|
#if defined(__MAC_10_6) || defined(__IPHONE_2_0)
|
||||||
|
/* SecItemCopyMatching() was introduced in iOS and Snow Leopard. If it
|
||||||
|
exists, let's use that to find the certificate. */
|
||||||
|
if(SecItemCopyMatching != NULL) {
|
||||||
|
CFTypeRef keys[4];
|
||||||
|
CFTypeRef values[4];
|
||||||
|
CFDictionaryRef query_dict;
|
||||||
|
CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
|
||||||
|
kCFStringEncodingUTF8);
|
||||||
|
|
||||||
|
/* Set up our search criteria and expected results: */
|
||||||
|
values[0] = kSecClassIdentity; /* we want a certificate and a key */
|
||||||
|
keys[0] = kSecClass;
|
||||||
|
values[1] = kCFBooleanTrue; /* we want a reference */
|
||||||
|
keys[1] = kSecReturnRef;
|
||||||
|
values[2] = kSecMatchLimitOne; /* one is enough, thanks */
|
||||||
|
keys[2] = kSecMatchLimit;
|
||||||
|
/* identity searches need a SecPolicyRef in order to work */
|
||||||
|
values[3] = SecPolicyCreateSSL(false, label_cf);
|
||||||
|
keys[3] = kSecMatchPolicy;
|
||||||
|
query_dict = CFDictionaryCreate(NULL, (const void **)keys,
|
||||||
|
(const void **)values, 4L,
|
||||||
|
&kCFCopyStringDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks);
|
||||||
|
CFRelease(values[3]);
|
||||||
|
CFRelease(label_cf);
|
||||||
|
|
||||||
|
/* Do we have a match? */
|
||||||
|
status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
|
||||||
|
CFRelease(query_dict);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||||
|
/* On Leopard, fall back to SecKeychainSearch. */
|
||||||
|
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||||
|
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
|
||||||
|
}
|
||||||
|
#elif (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||||
|
/* For developers building on Leopard, we have no choice but to fall back. */
|
||||||
|
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
|
||||||
|
#endif /* defined(__MAC_10_6) || defined(__IPHONE_2_0) */
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
||||||
int sockindex)
|
int sockindex)
|
||||||
{
|
{
|
||||||
@@ -704,6 +799,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
#endif
|
#endif
|
||||||
size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
|
size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
|
||||||
SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
|
SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
|
||||||
|
char *ssl_sessionid;
|
||||||
|
size_t ssl_sessionid_len;
|
||||||
OSStatus err = noErr;
|
OSStatus err = noErr;
|
||||||
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
|
||||||
int darwinver_maj = 0, darwinver_min = 0;
|
int darwinver_maj = 0, darwinver_min = 0;
|
||||||
@@ -839,8 +936,57 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
|
#endif /* defined(__MAC_10_8) || defined(__IPHONE_5_0) */
|
||||||
|
|
||||||
/* No need to load certificates here. SecureTransport uses the Keychain
|
if(data->set.str[STRING_KEY]) {
|
||||||
* (which is also part of the Security framework) to evaluate trust. */
|
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
|
||||||
|
"Transport. The private key must be in the Keychain.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->set.str[STRING_CERT]) {
|
||||||
|
SecIdentityRef cert_and_key = NULL;
|
||||||
|
|
||||||
|
/* User wants to authenticate with a client cert. Look for it: */
|
||||||
|
err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
|
||||||
|
if(err == noErr) {
|
||||||
|
SecCertificateRef cert = NULL;
|
||||||
|
CFTypeRef certs_c[1];
|
||||||
|
CFArrayRef certs;
|
||||||
|
|
||||||
|
/* If we found one, print it out: */
|
||||||
|
err = SecIdentityCopyCertificate(cert_and_key, &cert);
|
||||||
|
if(err == noErr) {
|
||||||
|
CFStringRef cert_summary = CopyCertSubject(cert);
|
||||||
|
char cert_summary_c[128];
|
||||||
|
|
||||||
|
if(cert_summary) {
|
||||||
|
memset(cert_summary_c, 0, 128);
|
||||||
|
if(CFStringGetCString(cert_summary,
|
||||||
|
cert_summary_c,
|
||||||
|
128,
|
||||||
|
kCFStringEncodingUTF8)) {
|
||||||
|
infof(data, "Client certificate: %s\n", cert_summary_c);
|
||||||
|
}
|
||||||
|
CFRelease(cert_summary);
|
||||||
|
CFRelease(cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
certs_c[0] = cert_and_key;
|
||||||
|
certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
|
||||||
|
&kCFTypeArrayCallBacks);
|
||||||
|
err = SSLSetCertificate(connssl->ssl_ctx, certs);
|
||||||
|
if(certs)
|
||||||
|
CFRelease(certs);
|
||||||
|
if(err != noErr) {
|
||||||
|
failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
|
||||||
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
|
}
|
||||||
|
CFRelease(cert_and_key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
failf(data, "SSL: Can't find the certificate \"%s\" and its private key "
|
||||||
|
"in the Keychain.", data->set.str[STRING_CERT]);
|
||||||
|
return CURLE_SSL_CERTPROBLEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* SSL always tries to verify the peer, this only says whether it should
|
/* SSL always tries to verify the peer, this only says whether it should
|
||||||
* fail to connect if the verification fails, or if it should continue
|
* fail to connect if the verification fails, or if it should continue
|
||||||
@@ -990,6 +1136,38 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
|
|||||||
Curl_safefree(all_ciphers);
|
Curl_safefree(all_ciphers);
|
||||||
Curl_safefree(allowed_ciphers);
|
Curl_safefree(allowed_ciphers);
|
||||||
|
|
||||||
|
/* Check if there's a cached ID we can/should use here! */
|
||||||
|
if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
|
||||||
|
&ssl_sessionid_len)) {
|
||||||
|
/* we got a session id, use it! */
|
||||||
|
err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
|
||||||
|
if(err != noErr) {
|
||||||
|
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
|
||||||
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
}
|
||||||
|
/* Informational message */
|
||||||
|
infof(data, "SSL re-using session ID\n");
|
||||||
|
}
|
||||||
|
/* If there isn't one, then let's make one up! This has to be done prior
|
||||||
|
to starting the handshake. */
|
||||||
|
else {
|
||||||
|
CURLcode retcode;
|
||||||
|
|
||||||
|
ssl_sessionid = malloc(256*sizeof(char));
|
||||||
|
ssl_sessionid_len = snprintf(ssl_sessionid, 256, "curl:%s:%hu",
|
||||||
|
conn->host.name, conn->remote_port);
|
||||||
|
err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
|
||||||
|
if(err != noErr) {
|
||||||
|
failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
|
||||||
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
}
|
||||||
|
retcode = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
|
||||||
|
if(retcode!= CURLE_OK) {
|
||||||
|
failf(data, "failed to store ssl session");
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
|
err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
|
||||||
if(err != noErr) {
|
if(err != noErr) {
|
||||||
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
|
failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
|
||||||
@@ -1059,6 +1237,20 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
|
|||||||
"certificate format");
|
"certificate format");
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
|
||||||
|
/* These are all certificate problems with the client: */
|
||||||
|
case errSecAuthFailed:
|
||||||
|
failf(data, "SSL authentication failed");
|
||||||
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
case errSSLPeerHandshakeFail:
|
||||||
|
failf(data, "SSL peer handshake failed, the server most likely "
|
||||||
|
"requires a client certificate to connect");
|
||||||
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
case errSSLPeerUnknownCA:
|
||||||
|
failf(data, "SSL server rejected the client certificate due to "
|
||||||
|
"the certificate being signed by an unknown certificate "
|
||||||
|
"authority");
|
||||||
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
|
||||||
/* This error is raised if the server's cert didn't match the server's
|
/* This error is raised if the server's cert didn't match the server's
|
||||||
host name: */
|
host name: */
|
||||||
case errSSLHostNameMismatch:
|
case errSSLHostNameMismatch:
|
||||||
@@ -1462,6 +1654,17 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curl_darwinssl_session_free(void *ptr)
|
||||||
|
{
|
||||||
|
/* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
|
||||||
|
cached session ID inside the Security framework. There is a private
|
||||||
|
function that does this, but I don't want to have to explain to you why I
|
||||||
|
got your application rejected from the App Store due to the use of a
|
||||||
|
private API, so the best we can do is free up our own char array that we
|
||||||
|
created way back in darwinssl_connect_step1... */
|
||||||
|
Curl_safefree(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
size_t Curl_darwinssl_version(char *buffer, size_t size)
|
size_t Curl_darwinssl_version(char *buffer, size_t size)
|
||||||
{
|
{
|
||||||
return snprintf(buffer, size, "SecureTransport");
|
return snprintf(buffer, size, "SecureTransport");
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ void Curl_darwinssl_close_all(struct SessionHandle *data);
|
|||||||
/* close a SSL connection */
|
/* close a SSL connection */
|
||||||
void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
|
void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
|
||||||
|
|
||||||
|
void Curl_darwinssl_session_free(void *ptr);
|
||||||
size_t Curl_darwinssl_version(char *buffer, size_t size);
|
size_t Curl_darwinssl_version(char *buffer, size_t size);
|
||||||
int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
|
int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
|
||||||
int Curl_darwinssl_check_cxn(struct connectdata *conn);
|
int Curl_darwinssl_check_cxn(struct connectdata *conn);
|
||||||
@@ -56,7 +57,7 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
|
|||||||
#define curlssl_cleanup() Curl_nop_stmt
|
#define curlssl_cleanup() Curl_nop_stmt
|
||||||
#define curlssl_connect Curl_darwinssl_connect
|
#define curlssl_connect Curl_darwinssl_connect
|
||||||
#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
|
#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
|
||||||
#define curlssl_session_free(x) Curl_nop_stmt
|
#define curlssl_session_free(x) Curl_darwinssl_session_free(x)
|
||||||
#define curlssl_close_all Curl_darwinssl_close_all
|
#define curlssl_close_all Curl_darwinssl_close_all
|
||||||
#define curlssl_close Curl_darwinssl_close
|
#define curlssl_close Curl_darwinssl_close
|
||||||
#define curlssl_shutdown(x,y) 0
|
#define curlssl_shutdown(x,y) 0
|
||||||
|
|||||||
@@ -87,9 +87,6 @@ extern curl_free_callback Curl_cfree;
|
|||||||
extern curl_realloc_callback Curl_crealloc;
|
extern curl_realloc_callback Curl_crealloc;
|
||||||
extern curl_strdup_callback Curl_cstrdup;
|
extern curl_strdup_callback Curl_cstrdup;
|
||||||
extern curl_calloc_callback Curl_ccalloc;
|
extern curl_calloc_callback Curl_ccalloc;
|
||||||
#ifdef WIN32
|
|
||||||
extern curl_wcsdup_callback Curl_cwcsdup;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CURLDEBUG
|
#ifndef CURLDEBUG
|
||||||
|
|
||||||
@@ -113,19 +110,6 @@ extern curl_wcsdup_callback Curl_cwcsdup;
|
|||||||
#undef free
|
#undef free
|
||||||
#define free(ptr) Curl_cfree(ptr)
|
#define free(ptr) Curl_cfree(ptr)
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
# undef wcsdup
|
|
||||||
# define wcsdup(ptr) Curl_cwcsdup(ptr)
|
|
||||||
# undef _wcsdup
|
|
||||||
# define _wcsdup(ptr) Curl_cwcsdup(ptr)
|
|
||||||
# undef _tcsdup
|
|
||||||
# ifdef UNICODE
|
|
||||||
# define _tcsdup(ptr) Curl_cwcsdup(ptr)
|
|
||||||
# else
|
|
||||||
# define _tcsdup(ptr) Curl_cstrdup(ptr)
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* CURLDEBUG */
|
#endif /* CURLDEBUG */
|
||||||
|
|
||||||
#else /* CURLX_NO_MEMORY_CALLBACKS */
|
#else /* CURLX_NO_MEMORY_CALLBACKS */
|
||||||
|
|||||||
@@ -25,13 +25,17 @@
|
|||||||
#include "pingpong.h"
|
#include "pingpong.h"
|
||||||
|
|
||||||
/* Authentication mechanism flags */
|
/* Authentication mechanism flags */
|
||||||
#define SASL_MECH_LOGIN 0x0001
|
#define SASL_MECH_LOGIN (1 << 0)
|
||||||
#define SASL_MECH_PLAIN 0x0002
|
#define SASL_MECH_PLAIN (1 << 1)
|
||||||
#define SASL_MECH_CRAM_MD5 0x0004
|
#define SASL_MECH_CRAM_MD5 (1 << 2)
|
||||||
#define SASL_MECH_DIGEST_MD5 0x0008
|
#define SASL_MECH_DIGEST_MD5 (1 << 3)
|
||||||
#define SASL_MECH_GSSAPI 0x0010
|
#define SASL_MECH_GSSAPI (1 << 4)
|
||||||
#define SASL_MECH_EXTERNAL 0x0020
|
#define SASL_MECH_EXTERNAL (1 << 5)
|
||||||
#define SASL_MECH_NTLM 0x0040
|
#define SASL_MECH_NTLM (1 << 6)
|
||||||
|
|
||||||
|
/* Authentication mechanism values */
|
||||||
|
#define SASL_AUTH_NONE 0
|
||||||
|
#define SASL_AUTH_ANY ~0
|
||||||
|
|
||||||
/* This is used to generate a base64 encoded PLAIN authentication message */
|
/* This is used to generate a base64 encoded PLAIN authentication message */
|
||||||
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
CURLcode Curl_sasl_create_plain_message(struct SessionHandle *data,
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
|
|||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
connssl->cred->cached = TRUE;
|
||||||
infof(data, "schannel: stored credential handle in session cache\n");
|
infof(data, "schannel: stored credential handle in session cache\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1063,7 +1064,6 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
*/
|
*/
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
struct curl_schannel_cred *cached_cred = NULL;
|
|
||||||
|
|
||||||
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
|
infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
|
||||||
conn->host.name, conn->remote_port);
|
conn->host.name, conn->remote_port);
|
||||||
@@ -1141,20 +1141,14 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
connssl->cred->refcount);
|
connssl->cred->refcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the handle refcount is zero, check if we have not cached it */
|
/* if the handle was not cached and the refcount is zero */
|
||||||
if(connssl->cred->refcount == 0) {
|
if(!connssl->cred->cached && connssl->cred->refcount == 0) {
|
||||||
if(Curl_ssl_getsessionid(conn, (void**)&cached_cred, NULL)) {
|
|
||||||
cached_cred = NULL;
|
|
||||||
}
|
|
||||||
/* if the handle was not cached, it is stale to be freed */
|
|
||||||
if(connssl->cred != cached_cred) {
|
|
||||||
infof(data, "schannel: clear credential handle\n");
|
infof(data, "schannel: clear credential handle\n");
|
||||||
s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle);
|
s_pSecFn->FreeCredentialsHandle(&connssl->cred->cred_handle);
|
||||||
Curl_safefree(connssl->cred);
|
Curl_safefree(connssl->cred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* free internal buffer for received encrypted data */
|
/* free internal buffer for received encrypted data */
|
||||||
if(connssl->encdata_buffer != NULL) {
|
if(connssl->encdata_buffer != NULL) {
|
||||||
@@ -1177,7 +1171,7 @@ void Curl_schannel_session_free(void *ptr)
|
|||||||
{
|
{
|
||||||
struct curl_schannel_cred *cred = ptr;
|
struct curl_schannel_cred *cred = ptr;
|
||||||
|
|
||||||
if(cred && cred->refcount == 0) {
|
if(cred && cred->cached && cred->refcount == 0) {
|
||||||
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
|
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
|
||||||
Curl_safefree(cred);
|
Curl_safefree(cred);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,7 +270,6 @@
|
|||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# include <tchar.h>
|
# include <tchar.h>
|
||||||
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -369,7 +368,9 @@
|
|||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# undef lseek
|
# undef lseek
|
||||||
# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence)
|
# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence)
|
||||||
|
# undef fstat
|
||||||
# define fstat(fdes,stp) _fstati64(fdes, stp)
|
# define fstat(fdes,stp) _fstati64(fdes, stp)
|
||||||
|
# undef stat
|
||||||
# define stat(fname,stp) _stati64(fname, stp)
|
# define stat(fname,stp) _stati64(fname, stp)
|
||||||
# define struct_stat struct _stati64
|
# define struct_stat struct _stati64
|
||||||
# define LSEEK_ERROR (__int64)-1
|
# define LSEEK_ERROR (__int64)-1
|
||||||
|
|||||||
36
lib/easy.c
36
lib/easy.c
@@ -73,6 +73,7 @@
|
|||||||
#include "non-ascii.h"
|
#include "non-ascii.h"
|
||||||
#include "warnless.h"
|
#include "warnless.h"
|
||||||
#include "conncache.h"
|
#include "conncache.h"
|
||||||
|
#include "multiif.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@@ -197,9 +198,6 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
|
|||||||
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
|
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
|
||||||
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
||||||
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
|
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||||
#ifdef WIN32
|
|
||||||
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)wcsdup;
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* Symbian OS doesn't support initialization to code in writeable static data.
|
* Symbian OS doesn't support initialization to code in writeable static data.
|
||||||
@@ -231,9 +229,6 @@ CURLcode curl_global_init(long flags)
|
|||||||
Curl_crealloc = (curl_realloc_callback)realloc;
|
Curl_crealloc = (curl_realloc_callback)realloc;
|
||||||
Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
Curl_cstrdup = (curl_strdup_callback)system_strdup;
|
||||||
Curl_ccalloc = (curl_calloc_callback)calloc;
|
Curl_ccalloc = (curl_calloc_callback)calloc;
|
||||||
#ifdef WIN32
|
|
||||||
Curl_cwcsdup = (curl_wcsdup_callback)wcsdup;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(flags & CURL_GLOBAL_SSL)
|
if(flags & CURL_GLOBAL_SSL)
|
||||||
if(!Curl_ssl_init()) {
|
if(!Curl_ssl_init()) {
|
||||||
@@ -425,6 +420,9 @@ CURLcode curl_easy_perform(CURL *easy)
|
|||||||
bool done = FALSE;
|
bool done = FALSE;
|
||||||
int rc;
|
int rc;
|
||||||
struct SessionHandle *data = easy;
|
struct SessionHandle *data = easy;
|
||||||
|
int without_fds = 0; /* count number of consecutive returns from
|
||||||
|
curl_multi_wait() without any filedescriptors */
|
||||||
|
struct timeval before;
|
||||||
|
|
||||||
if(!easy)
|
if(!easy)
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
@@ -437,7 +435,9 @@ CURLcode curl_easy_perform(CURL *easy)
|
|||||||
if(data->multi_easy)
|
if(data->multi_easy)
|
||||||
multi = data->multi_easy;
|
multi = data->multi_easy;
|
||||||
else {
|
else {
|
||||||
multi = curl_multi_init();
|
/* this multi handle will only ever have a single easy handled attached
|
||||||
|
to it, so make it use minimal hashes */
|
||||||
|
multi = Curl_multi_handle(1, 3);
|
||||||
if(!multi)
|
if(!multi)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
data->multi_easy = multi;
|
data->multi_easy = multi;
|
||||||
@@ -463,6 +463,7 @@ CURLcode curl_easy_perform(CURL *easy)
|
|||||||
int still_running;
|
int still_running;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
before = curlx_tvnow();
|
||||||
mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
|
mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
|
||||||
|
|
||||||
if(mcode == CURLM_OK) {
|
if(mcode == CURLM_OK) {
|
||||||
@@ -471,6 +472,27 @@ CURLcode curl_easy_perform(CURL *easy)
|
|||||||
code = CURLE_RECV_ERROR;
|
code = CURLE_RECV_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if(ret == 0) {
|
||||||
|
struct timeval after = curlx_tvnow();
|
||||||
|
/* If it returns without any filedescriptor instantly, we need to
|
||||||
|
avoid busy-looping during periods where it has nothing particular
|
||||||
|
to wait for */
|
||||||
|
if(curlx_tvdiff(after, before) <= 10) {
|
||||||
|
without_fds++;
|
||||||
|
if(without_fds > 2) {
|
||||||
|
int sleep_ms = without_fds * 50;
|
||||||
|
if(sleep_ms > 1000)
|
||||||
|
sleep_ms = 1000;
|
||||||
|
Curl_wait_ms(sleep_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* it wasn't "instant", restart counter */
|
||||||
|
without_fds = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* got file descriptor, restart counter */
|
||||||
|
without_fds = 0;
|
||||||
|
|
||||||
mcode = curl_multi_perform(multi, &still_running);
|
mcode = curl_multi_perform(multi, &still_running);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -159,7 +159,8 @@ CURLcode Curl_urldecode(struct SessionHandle *data,
|
|||||||
|
|
||||||
while(--alloc > 0) {
|
while(--alloc > 0) {
|
||||||
in = *string;
|
in = *string;
|
||||||
if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
|
if(('%' == in) && (alloc > 2) &&
|
||||||
|
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
|
||||||
/* this is two hexadecimal digits following a '%' */
|
/* this is two hexadecimal digits following a '%' */
|
||||||
char hexstr[3];
|
char hexstr[3];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|||||||
32
lib/ftp.c
32
lib/ftp.c
@@ -1951,13 +1951,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
|||||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->set.str[STRING_PROXY] && *data->set.str[STRING_PROXY]) {
|
if(conn->bits.proxy) {
|
||||||
/*
|
/*
|
||||||
* This is a tunnel through a http proxy and we need to connect to the
|
* This connection uses a proxy and we need to connect to the proxy again
|
||||||
* proxy again here.
|
* here. We don't want to rely on a former host lookup that might've
|
||||||
*
|
* expired now, instead we remake the lookup here and now!
|
||||||
* We don't want to rely on a former host lookup that might've expired
|
|
||||||
* now, instead we remake the lookup here and now!
|
|
||||||
*/
|
*/
|
||||||
rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
|
rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
|
||||||
if(rc == CURLRESOLV_PENDING)
|
if(rc == CURLRESOLV_PENDING)
|
||||||
@@ -2711,7 +2709,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||||||
/* we have now received a full FTP server response */
|
/* we have now received a full FTP server response */
|
||||||
switch(ftpc->state) {
|
switch(ftpc->state) {
|
||||||
case FTP_WAIT220:
|
case FTP_WAIT220:
|
||||||
if(ftpcode != 220) {
|
if(ftpcode == 230)
|
||||||
|
/* 230 User logged in - already! */
|
||||||
|
return ftp_state_user_resp(conn, ftpcode, ftpc->state);
|
||||||
|
else if(ftpcode != 220) {
|
||||||
failf(data, "Got a %03d ftp-server response when 220 was expected",
|
failf(data, "Got a %03d ftp-server response when 220 was expected",
|
||||||
ftpcode);
|
ftpcode);
|
||||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||||
@@ -4316,13 +4317,17 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
slash_pos=strrchr(cur_pos, '/');
|
slash_pos=strrchr(cur_pos, '/');
|
||||||
if(slash_pos || !*cur_pos) {
|
if(slash_pos || !*cur_pos) {
|
||||||
|
size_t dirlen = slash_pos-cur_pos;
|
||||||
|
|
||||||
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
|
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
|
||||||
if(!ftpc->dirs)
|
if(!ftpc->dirs)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
if(!dirlen)
|
||||||
|
dirlen++;
|
||||||
|
|
||||||
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
|
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
|
||||||
slash_pos ?
|
slash_pos ? curlx_sztosi(dirlen) : 1,
|
||||||
curlx_sztosi(slash_pos-cur_pos) : 1,
|
|
||||||
NULL);
|
NULL);
|
||||||
if(!ftpc->dirs[0]) {
|
if(!ftpc->dirs[0]) {
|
||||||
freedirs(ftpc);
|
freedirs(ftpc);
|
||||||
@@ -4377,6 +4382,15 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
||||||
|
if(!ftpc->dirdepth) {
|
||||||
|
/* path starts with a slash, add that as a directory */
|
||||||
|
ftpc->dirs[ftpc->dirdepth] = strdup("/");
|
||||||
|
if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
|
||||||
|
failf(data, "no memory");
|
||||||
|
freedirs(ftpc);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
|
|||||||
info->httpcode = 0;
|
info->httpcode = 0;
|
||||||
info->httpversion=0;
|
info->httpversion=0;
|
||||||
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
||||||
|
info->timecond=0;
|
||||||
|
|
||||||
if(info->contenttype)
|
if(info->contenttype)
|
||||||
free(info->contenttype);
|
free(info->contenttype);
|
||||||
|
|||||||
@@ -267,6 +267,38 @@ static void md5_to_ascii(unsigned char *source, /* 16 bytes */
|
|||||||
snprintf((char *)&dest[i*2], 3, "%02x", source[i]);
|
snprintf((char *)&dest[i*2], 3, "%02x", source[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform quoted-string escaping as described in RFC2616 and its errata */
|
||||||
|
static char *string_quoted(const char *source)
|
||||||
|
{
|
||||||
|
char *dest, *d;
|
||||||
|
const char *s = source;
|
||||||
|
size_t n = 1; /* null terminator */
|
||||||
|
|
||||||
|
/* Calculate size needed */
|
||||||
|
while(*s) {
|
||||||
|
++n;
|
||||||
|
if(*s == '"' || *s == '\\') {
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = (char *)malloc(n);
|
||||||
|
if(dest) {
|
||||||
|
s = source;
|
||||||
|
d = dest;
|
||||||
|
while(*s) {
|
||||||
|
if(*s == '"' || *s == '\\') {
|
||||||
|
*d++ = '\\';
|
||||||
|
}
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
*d = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
CURLcode Curl_output_digest(struct connectdata *conn,
|
CURLcode Curl_output_digest(struct connectdata *conn,
|
||||||
bool proxy,
|
bool proxy,
|
||||||
const unsigned char *request,
|
const unsigned char *request,
|
||||||
@@ -289,6 +321,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
char **allocuserpwd;
|
char **allocuserpwd;
|
||||||
size_t userlen;
|
size_t userlen;
|
||||||
const char *userp;
|
const char *userp;
|
||||||
|
char *userp_quoted;
|
||||||
const char *passwdp;
|
const char *passwdp;
|
||||||
struct auth *authp;
|
struct auth *authp;
|
||||||
|
|
||||||
@@ -425,16 +458,20 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
else
|
else
|
||||||
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
|
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
|
||||||
|
|
||||||
|
if(d->qop && Curl_raw_equal(d->qop, "auth-int")) {
|
||||||
|
/* We don't support auth-int for PUT or POST at the moment.
|
||||||
|
TODO: replace md5 of empty string with entity-body for PUT/POST */
|
||||||
|
unsigned char *md5this2 = (unsigned char *)
|
||||||
|
aprintf("%s:%s", md5this, "d41d8cd98f00b204e9800998ecf8427e");
|
||||||
|
free(md5this);
|
||||||
|
md5this = md5this2;
|
||||||
|
}
|
||||||
|
|
||||||
if(!md5this) {
|
if(!md5this) {
|
||||||
free(ha1);
|
free(ha1);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d->qop && Curl_raw_equal(d->qop, "auth-int")) {
|
|
||||||
/* We don't support auth-int at the moment. I can't see a easy way to get
|
|
||||||
entity-body here */
|
|
||||||
/* TODO: Append H(entity-body)*/
|
|
||||||
}
|
|
||||||
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
|
||||||
Curl_md5it(md5buf, md5this);
|
Curl_md5it(md5buf, md5this);
|
||||||
free(md5this); /* free this again */
|
free(md5this); /* free this again */
|
||||||
@@ -468,7 +505,18 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
|
|
||||||
Authorization: Digest username="testuser", realm="testrealm", \
|
Authorization: Digest username="testuser", realm="testrealm", \
|
||||||
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
|
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
|
||||||
|
|
||||||
|
Digest parameters are all quoted strings. Username which is provided by
|
||||||
|
the user will need double quotes and backslashes within it escaped. For
|
||||||
|
the other fields, this shouldn't be an issue. realm, nonce, and opaque
|
||||||
|
are copied as is from the server, escapes and all. cnonce is generated
|
||||||
|
with web-safe characters. uri is already percent encoded. nc is 8 hex
|
||||||
|
characters. algorithm and qop with standard values only contain web-safe
|
||||||
|
chracters.
|
||||||
*/
|
*/
|
||||||
|
userp_quoted = string_quoted(userp);
|
||||||
|
if(!*userp_quoted)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if(d->qop) {
|
if(d->qop) {
|
||||||
*allocuserpwd =
|
*allocuserpwd =
|
||||||
@@ -482,7 +530,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
"qop=%s, "
|
"qop=%s, "
|
||||||
"response=\"%s\"",
|
"response=\"%s\"",
|
||||||
proxy?"Proxy-":"",
|
proxy?"Proxy-":"",
|
||||||
userp,
|
userp_quoted,
|
||||||
d->realm,
|
d->realm,
|
||||||
d->nonce,
|
d->nonce,
|
||||||
uripath, /* this is the PATH part of the URL */
|
uripath, /* this is the PATH part of the URL */
|
||||||
@@ -505,12 +553,13 @@ CURLcode Curl_output_digest(struct connectdata *conn,
|
|||||||
"uri=\"%s\", "
|
"uri=\"%s\", "
|
||||||
"response=\"%s\"",
|
"response=\"%s\"",
|
||||||
proxy?"Proxy-":"",
|
proxy?"Proxy-":"",
|
||||||
userp,
|
userp_quoted,
|
||||||
d->realm,
|
d->realm,
|
||||||
d->nonce,
|
d->nonce,
|
||||||
uripath, /* this is the PATH part of the URL */
|
uripath, /* this is the PATH part of the URL */
|
||||||
request_digest);
|
request_digest);
|
||||||
}
|
}
|
||||||
|
free(userp_quoted);
|
||||||
if(!*allocuserpwd)
|
if(!*allocuserpwd)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
|||||||
524
lib/imap.c
524
lib/imap.c
@@ -86,8 +86,6 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/* Local API functions */
|
/* Local API functions */
|
||||||
static CURLcode imap_parse_url_path(struct connectdata *conn);
|
|
||||||
static CURLcode imap_parse_custom_request(struct connectdata *conn);
|
|
||||||
static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
|
static CURLcode imap_regular_transfer(struct connectdata *conn, bool *done);
|
||||||
static CURLcode imap_do(struct connectdata *conn, bool *done);
|
static CURLcode imap_do(struct connectdata *conn, bool *done);
|
||||||
static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
static CURLcode imap_done(struct connectdata *conn, CURLcode status,
|
||||||
@@ -99,6 +97,11 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
|
|||||||
int numsocks);
|
int numsocks);
|
||||||
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
|
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done);
|
||||||
static CURLcode imap_setup_connection(struct connectdata *conn);
|
static CURLcode imap_setup_connection(struct connectdata *conn);
|
||||||
|
static char *imap_atom(const char *str);
|
||||||
|
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...);
|
||||||
|
static CURLcode imap_parse_url_options(struct connectdata *conn);
|
||||||
|
static CURLcode imap_parse_url_path(struct connectdata *conn);
|
||||||
|
static CURLcode imap_parse_custom_request(struct connectdata *conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IMAP protocol handler.
|
* IMAP protocol handler.
|
||||||
@@ -213,119 +216,6 @@ static void imap_to_imaps(struct connectdata *conn)
|
|||||||
#define imap_to_imaps(x) Curl_nop_stmt
|
#define imap_to_imaps(x) Curl_nop_stmt
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
* imap_sendf()
|
|
||||||
*
|
|
||||||
* Sends the formated string as an IMAP command to the server.
|
|
||||||
*
|
|
||||||
* Designed to never block.
|
|
||||||
*/
|
|
||||||
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct imap_conn *imapc = &conn->proto.imapc;
|
|
||||||
char *taggedfmt;
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
|
|
||||||
/* Calculate the next command ID wrapping at 3 digits */
|
|
||||||
imapc->cmdid = (imapc->cmdid + 1) % 1000;
|
|
||||||
|
|
||||||
/* Calculate the tag based on the connection ID and command ID */
|
|
||||||
snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
|
|
||||||
'A' + (conn->connection_id % 26), imapc->cmdid);
|
|
||||||
|
|
||||||
/* Prefix the format with the tag */
|
|
||||||
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
|
|
||||||
if(!taggedfmt)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
/* Send the data with the tag */
|
|
||||||
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
|
|
||||||
|
|
||||||
Curl_safefree(taggedfmt);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
* imap_atom()
|
|
||||||
*
|
|
||||||
* Checks the input string for characters that need escaping and returns an
|
|
||||||
* atom ready for sending to the server.
|
|
||||||
*
|
|
||||||
* The returned string needs to be freed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static char *imap_atom(const char *str)
|
|
||||||
{
|
|
||||||
const char *p1;
|
|
||||||
char *p2;
|
|
||||||
size_t backsp_count = 0;
|
|
||||||
size_t quote_count = 0;
|
|
||||||
bool space_exists = FALSE;
|
|
||||||
size_t newlen = 0;
|
|
||||||
char *newstr = NULL;
|
|
||||||
|
|
||||||
if(!str)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Count any unescapped characters */
|
|
||||||
p1 = str;
|
|
||||||
while(*p1) {
|
|
||||||
if(*p1 == '\\')
|
|
||||||
backsp_count++;
|
|
||||||
else if(*p1 == '"')
|
|
||||||
quote_count++;
|
|
||||||
else if(*p1 == ' ')
|
|
||||||
space_exists = TRUE;
|
|
||||||
|
|
||||||
p1++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does the input contain any unescapped characters? */
|
|
||||||
if(!backsp_count && !quote_count && !space_exists)
|
|
||||||
return strdup(str);
|
|
||||||
|
|
||||||
/* Calculate the new string length */
|
|
||||||
newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0);
|
|
||||||
|
|
||||||
/* Allocate the new string */
|
|
||||||
newstr = (char *) malloc((newlen + 1) * sizeof(char));
|
|
||||||
if(!newstr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Surround the string in quotes if necessary */
|
|
||||||
p2 = newstr;
|
|
||||||
if(space_exists) {
|
|
||||||
newstr[0] = '"';
|
|
||||||
newstr[newlen - 1] = '"';
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the string, escaping backslash and quote characters along the way */
|
|
||||||
p1 = str;
|
|
||||||
while(*p1) {
|
|
||||||
if(*p1 == '\\' || *p1 == '"') {
|
|
||||||
*p2 = '\\';
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*p2 = *p1;
|
|
||||||
|
|
||||||
p1++;
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Terminate the string */
|
|
||||||
newstr[newlen] = '\0';
|
|
||||||
|
|
||||||
return newstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* imap_matchresp()
|
* imap_matchresp()
|
||||||
@@ -635,6 +525,7 @@ static CURLcode imap_perform_login(struct connectdata *conn)
|
|||||||
static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
struct imap_conn *imapc = &conn->proto.imapc;
|
struct imap_conn *imapc = &conn->proto.imapc;
|
||||||
const char *mech = NULL;
|
const char *mech = NULL;
|
||||||
char *initresp = NULL;
|
char *initresp = NULL;
|
||||||
@@ -653,12 +544,14 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
|||||||
/* Calculate the supported authentication mechanism by decreasing order of
|
/* Calculate the supported authentication mechanism by decreasing order of
|
||||||
security */
|
security */
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
if(imapc->authmechs & SASL_MECH_DIGEST_MD5) {
|
if((imapc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||||
|
(imapc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||||
mech = "DIGEST-MD5";
|
mech = "DIGEST-MD5";
|
||||||
state1 = IMAP_AUTHENTICATE_DIGESTMD5;
|
state1 = IMAP_AUTHENTICATE_DIGESTMD5;
|
||||||
imapc->authused = SASL_MECH_DIGEST_MD5;
|
imapc->authused = SASL_MECH_DIGEST_MD5;
|
||||||
}
|
}
|
||||||
else if(imapc->authmechs & SASL_MECH_CRAM_MD5) {
|
else if((imapc->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||||
|
(imapc->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||||
mech = "CRAM-MD5";
|
mech = "CRAM-MD5";
|
||||||
state1 = IMAP_AUTHENTICATE_CRAMMD5;
|
state1 = IMAP_AUTHENTICATE_CRAMMD5;
|
||||||
imapc->authused = SASL_MECH_CRAM_MD5;
|
imapc->authused = SASL_MECH_CRAM_MD5;
|
||||||
@@ -666,43 +559,44 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NTLM
|
#ifdef USE_NTLM
|
||||||
if(imapc->authmechs & SASL_MECH_NTLM) {
|
if((imapc->authmechs & SASL_MECH_NTLM) &&
|
||||||
|
(imapc->prefmech & SASL_MECH_NTLM)) {
|
||||||
mech = "NTLM";
|
mech = "NTLM";
|
||||||
state1 = IMAP_AUTHENTICATE_NTLM;
|
state1 = IMAP_AUTHENTICATE_NTLM;
|
||||||
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
|
state2 = IMAP_AUTHENTICATE_NTLM_TYPE2MSG;
|
||||||
imapc->authused = SASL_MECH_NTLM;
|
imapc->authused = SASL_MECH_NTLM;
|
||||||
|
|
||||||
if(imapc->ir_supported)
|
if(imapc->ir_supported || data->set.sasl_ir)
|
||||||
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||||
&conn->ntlm,
|
&conn->ntlm,
|
||||||
&initresp, &len);
|
&initresp, &len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(imapc->authmechs & SASL_MECH_LOGIN) {
|
if((imapc->authmechs & SASL_MECH_LOGIN) &&
|
||||||
|
(imapc->prefmech & SASL_MECH_LOGIN)) {
|
||||||
mech = "LOGIN";
|
mech = "LOGIN";
|
||||||
state1 = IMAP_AUTHENTICATE_LOGIN;
|
state1 = IMAP_AUTHENTICATE_LOGIN;
|
||||||
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
|
state2 = IMAP_AUTHENTICATE_LOGIN_PASSWD;
|
||||||
imapc->authused = SASL_MECH_LOGIN;
|
imapc->authused = SASL_MECH_LOGIN;
|
||||||
|
|
||||||
if(imapc->ir_supported)
|
if(imapc->ir_supported || data->set.sasl_ir)
|
||||||
result = Curl_sasl_create_login_message(conn->data, conn->user,
|
result = Curl_sasl_create_login_message(conn->data, conn->user,
|
||||||
&initresp, &len);
|
&initresp, &len);
|
||||||
}
|
}
|
||||||
else if(imapc->authmechs & SASL_MECH_PLAIN) {
|
else if((imapc->authmechs & SASL_MECH_PLAIN) &&
|
||||||
|
(imapc->prefmech & SASL_MECH_PLAIN)) {
|
||||||
mech = "PLAIN";
|
mech = "PLAIN";
|
||||||
state1 = IMAP_AUTHENTICATE_PLAIN;
|
state1 = IMAP_AUTHENTICATE_PLAIN;
|
||||||
state2 = IMAP_AUTHENTICATE_FINAL;
|
state2 = IMAP_AUTHENTICATE_FINAL;
|
||||||
imapc->authused = SASL_MECH_PLAIN;
|
imapc->authused = SASL_MECH_PLAIN;
|
||||||
|
|
||||||
if(imapc->ir_supported)
|
if(imapc->ir_supported || data->set.sasl_ir)
|
||||||
result = Curl_sasl_create_plain_message(conn->data, conn->user,
|
result = Curl_sasl_create_plain_message(conn->data, conn->user,
|
||||||
conn->passwd, &initresp, &len);
|
conn->passwd, &initresp, &len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result)
|
if(!result) {
|
||||||
return result;
|
|
||||||
|
|
||||||
if(mech) {
|
if(mech) {
|
||||||
/* Perform SASL based authentication */
|
/* Perform SASL based authentication */
|
||||||
if(initresp) {
|
if(initresp) {
|
||||||
@@ -728,6 +622,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn)
|
|||||||
infof(conn->data, "No known authentication mechanisms supported!\n");
|
infof(conn->data, "No known authentication mechanisms supported!\n");
|
||||||
result = CURLE_LOGIN_DENIED;
|
result = CURLE_LOGIN_DENIED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1793,8 +1688,10 @@ static int imap_getsock(struct connectdata *conn, curl_socket_t *socks,
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* imap_connect() should do everything that is to be considered a part of
|
* imap_connect()
|
||||||
* the connection phase.
|
*
|
||||||
|
* This function should do everything that is to be considered a part of the
|
||||||
|
* connection phase.
|
||||||
*
|
*
|
||||||
* The variable 'done' points to will be TRUE if the protocol-layer connect
|
* The variable 'done' points to will be TRUE if the protocol-layer connect
|
||||||
* phase is done when this function returns, or FALSE is not. When called as
|
* phase is done when this function returns, or FALSE is not. When called as
|
||||||
@@ -1826,9 +1723,17 @@ static CURLcode imap_connect(struct connectdata *conn, bool *done)
|
|||||||
pp->endofresp = imap_endofresp;
|
pp->endofresp = imap_endofresp;
|
||||||
pp->conn = conn;
|
pp->conn = conn;
|
||||||
|
|
||||||
|
/* Set the default preferred authentication mechanism */
|
||||||
|
imapc->prefmech = SASL_AUTH_ANY;
|
||||||
|
|
||||||
/* Initialise the pingpong layer */
|
/* Initialise the pingpong layer */
|
||||||
Curl_pp_init(pp);
|
Curl_pp_init(pp);
|
||||||
|
|
||||||
|
/* Parse the URL options */
|
||||||
|
result = imap_parse_url_options(conn);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
/* Start off waiting for the server greeting response */
|
/* Start off waiting for the server greeting response */
|
||||||
state(conn, IMAP_SERVERGREET);
|
state(conn, IMAP_SERVERGREET);
|
||||||
|
|
||||||
@@ -2044,6 +1949,218 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Call this when the DO phase has completed */
|
||||||
|
static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
|
||||||
|
{
|
||||||
|
struct IMAP *imap = conn->data->state.proto.imap;
|
||||||
|
|
||||||
|
(void)connected;
|
||||||
|
|
||||||
|
if(imap->transfer != FTPTRANSFER_BODY)
|
||||||
|
/* no data to transfer */
|
||||||
|
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called from multi.c while DOing */
|
||||||
|
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
|
||||||
|
{
|
||||||
|
CURLcode result = imap_multi_statemach(conn, dophase_done);
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
DEBUGF(infof(conn->data, "DO phase failed\n"));
|
||||||
|
else if(*dophase_done) {
|
||||||
|
result = imap_dophase_done(conn, FALSE /* not connected */);
|
||||||
|
|
||||||
|
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* imap_regular_transfer()
|
||||||
|
*
|
||||||
|
* The input argument is already checked for validity.
|
||||||
|
*
|
||||||
|
* Performs all commands done before a regular transfer between a local and a
|
||||||
|
* remote host.
|
||||||
|
*/
|
||||||
|
static CURLcode imap_regular_transfer(struct connectdata *conn,
|
||||||
|
bool *dophase_done)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
bool connected = FALSE;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
/* Make sure size is unknown at this point */
|
||||||
|
data->req.size = -1;
|
||||||
|
|
||||||
|
/* Set the progress data */
|
||||||
|
Curl_pgrsSetUploadCounter(data, 0);
|
||||||
|
Curl_pgrsSetDownloadCounter(data, 0);
|
||||||
|
Curl_pgrsSetUploadSize(data, 0);
|
||||||
|
Curl_pgrsSetDownloadSize(data, 0);
|
||||||
|
|
||||||
|
/* Carry out the perform */
|
||||||
|
result = imap_perform(conn, &connected, dophase_done);
|
||||||
|
|
||||||
|
/* Perform post DO phase operations if necessary */
|
||||||
|
if(!result && *dophase_done)
|
||||||
|
result = imap_dophase_done(conn, connected);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CURLcode imap_setup_connection(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
||||||
|
/* Unless we have asked to tunnel IMAP operations through the proxy, we
|
||||||
|
switch and use HTTP operations only */
|
||||||
|
#ifndef CURL_DISABLE_HTTP
|
||||||
|
if(conn->handler == &Curl_handler_imap)
|
||||||
|
conn->handler = &Curl_handler_imap_proxy;
|
||||||
|
else {
|
||||||
|
#ifdef USE_SSL
|
||||||
|
conn->handler = &Curl_handler_imaps_proxy;
|
||||||
|
#else
|
||||||
|
failf(data, "IMAPS not supported!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We explicitly mark this connection as persistent here as we're doing
|
||||||
|
IMAP over HTTP and thus we accidentally avoid setting this value
|
||||||
|
otherwise */
|
||||||
|
conn->bits.close = FALSE;
|
||||||
|
#else
|
||||||
|
failf(data, "IMAP over http proxy requires HTTP support built-in!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
data->state.path++; /* don't include the initial slash */
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* imap_sendf()
|
||||||
|
*
|
||||||
|
* Sends the formated string as an IMAP command to the server.
|
||||||
|
*
|
||||||
|
* Designed to never block.
|
||||||
|
*/
|
||||||
|
static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct imap_conn *imapc = &conn->proto.imapc;
|
||||||
|
char *taggedfmt;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
/* Calculate the next command ID wrapping at 3 digits */
|
||||||
|
imapc->cmdid = (imapc->cmdid + 1) % 1000;
|
||||||
|
|
||||||
|
/* Calculate the tag based on the connection ID and command ID */
|
||||||
|
snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
|
||||||
|
'A' + (conn->connection_id % 26), imapc->cmdid);
|
||||||
|
|
||||||
|
/* Prefix the format with the tag */
|
||||||
|
taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
|
||||||
|
if(!taggedfmt)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* Send the data with the tag */
|
||||||
|
result = Curl_pp_vsendf(&imapc->pp, taggedfmt, ap);
|
||||||
|
|
||||||
|
Curl_safefree(taggedfmt);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* imap_atom()
|
||||||
|
*
|
||||||
|
* Checks the input string for characters that need escaping and returns an
|
||||||
|
* atom ready for sending to the server.
|
||||||
|
*
|
||||||
|
* The returned string needs to be freed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static char *imap_atom(const char *str)
|
||||||
|
{
|
||||||
|
const char *p1;
|
||||||
|
char *p2;
|
||||||
|
size_t backsp_count = 0;
|
||||||
|
size_t quote_count = 0;
|
||||||
|
bool space_exists = FALSE;
|
||||||
|
size_t newlen = 0;
|
||||||
|
char *newstr = NULL;
|
||||||
|
|
||||||
|
if(!str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Count any unescapped characters */
|
||||||
|
p1 = str;
|
||||||
|
while(*p1) {
|
||||||
|
if(*p1 == '\\')
|
||||||
|
backsp_count++;
|
||||||
|
else if(*p1 == '"')
|
||||||
|
quote_count++;
|
||||||
|
else if(*p1 == ' ')
|
||||||
|
space_exists = TRUE;
|
||||||
|
|
||||||
|
p1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does the input contain any unescapped characters? */
|
||||||
|
if(!backsp_count && !quote_count && !space_exists)
|
||||||
|
return strdup(str);
|
||||||
|
|
||||||
|
/* Calculate the new string length */
|
||||||
|
newlen = strlen(str) + backsp_count + quote_count + (space_exists ? 2 : 0);
|
||||||
|
|
||||||
|
/* Allocate the new string */
|
||||||
|
newstr = (char *) malloc((newlen + 1) * sizeof(char));
|
||||||
|
if(!newstr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Surround the string in quotes if necessary */
|
||||||
|
p2 = newstr;
|
||||||
|
if(space_exists) {
|
||||||
|
newstr[0] = '"';
|
||||||
|
newstr[newlen - 1] = '"';
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the string, escaping backslash and quote characters along the way */
|
||||||
|
p1 = str;
|
||||||
|
while(*p1) {
|
||||||
|
if(*p1 == '\\' || *p1 == '"') {
|
||||||
|
*p2 = '\\';
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p2 = *p1;
|
||||||
|
|
||||||
|
p1++;
|
||||||
|
p2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate the string */
|
||||||
|
newstr[newlen] = '\0';
|
||||||
|
|
||||||
|
return newstr;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* imap_is_bchar()
|
* imap_is_bchar()
|
||||||
@@ -2082,6 +2199,52 @@ static bool imap_is_bchar(char ch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* imap_parse_url_options()
|
||||||
|
*
|
||||||
|
* Parse the URL login options.
|
||||||
|
*/
|
||||||
|
static CURLcode imap_parse_url_options(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct imap_conn *imapc = &conn->proto.imapc;
|
||||||
|
const char *options = conn->options;
|
||||||
|
const char *ptr = options;
|
||||||
|
|
||||||
|
if(options) {
|
||||||
|
const char *key = ptr;
|
||||||
|
|
||||||
|
while(*ptr && *ptr != '=')
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if(strnequal(key, "AUTH", 4)) {
|
||||||
|
const char *value = ptr + 1;
|
||||||
|
|
||||||
|
if(strequal(value, "*"))
|
||||||
|
imapc->prefmech = SASL_AUTH_ANY;
|
||||||
|
else if(strequal(value, "LOGIN"))
|
||||||
|
imapc->prefmech = SASL_MECH_LOGIN;
|
||||||
|
else if(strequal(value, "PLAIN"))
|
||||||
|
imapc->prefmech = SASL_MECH_PLAIN;
|
||||||
|
else if(strequal(value, "CRAM-MD5"))
|
||||||
|
imapc->prefmech = SASL_MECH_CRAM_MD5;
|
||||||
|
else if(strequal(value, "DIGEST-MD5"))
|
||||||
|
imapc->prefmech = SASL_MECH_DIGEST_MD5;
|
||||||
|
else if(strequal(value, "GSSAPI"))
|
||||||
|
imapc->prefmech = SASL_MECH_GSSAPI;
|
||||||
|
else if(strequal(value, "NTLM"))
|
||||||
|
imapc->prefmech = SASL_MECH_NTLM;
|
||||||
|
else
|
||||||
|
imapc->prefmech = SASL_AUTH_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = CURLE_URL_MALFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* imap_parse_url_path()
|
* imap_parse_url_path()
|
||||||
@@ -2192,6 +2355,12 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* imap_parse_custom_request()
|
||||||
|
*
|
||||||
|
* Parse the custom request.
|
||||||
|
*/
|
||||||
static CURLcode imap_parse_custom_request(struct connectdata *conn)
|
static CURLcode imap_parse_custom_request(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
@@ -2223,103 +2392,4 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call this when the DO phase has completed */
|
|
||||||
static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
|
|
||||||
{
|
|
||||||
struct IMAP *imap = conn->data->state.proto.imap;
|
|
||||||
|
|
||||||
(void)connected;
|
|
||||||
|
|
||||||
if(imap->transfer != FTPTRANSFER_BODY)
|
|
||||||
/* no data to transfer */
|
|
||||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Called from multi.c while DOing */
|
|
||||||
static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done)
|
|
||||||
{
|
|
||||||
CURLcode result = imap_multi_statemach(conn, dophase_done);
|
|
||||||
|
|
||||||
if(result)
|
|
||||||
DEBUGF(infof(conn->data, "DO phase failed\n"));
|
|
||||||
else if(*dophase_done) {
|
|
||||||
result = imap_dophase_done(conn, FALSE /* not connected */);
|
|
||||||
|
|
||||||
DEBUGF(infof(conn->data, "DO phase is complete\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
* imap_regular_transfer()
|
|
||||||
*
|
|
||||||
* The input argument is already checked for validity.
|
|
||||||
*
|
|
||||||
* Performs all commands done before a regular transfer between a local and a
|
|
||||||
* remote host.
|
|
||||||
*/
|
|
||||||
static CURLcode imap_regular_transfer(struct connectdata *conn,
|
|
||||||
bool *dophase_done)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
bool connected = FALSE;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
|
|
||||||
/* Make sure size is unknown at this point */
|
|
||||||
data->req.size = -1;
|
|
||||||
|
|
||||||
/* Set the progress data */
|
|
||||||
Curl_pgrsSetUploadCounter(data, 0);
|
|
||||||
Curl_pgrsSetDownloadCounter(data, 0);
|
|
||||||
Curl_pgrsSetUploadSize(data, 0);
|
|
||||||
Curl_pgrsSetDownloadSize(data, 0);
|
|
||||||
|
|
||||||
/* Carry out the perform */
|
|
||||||
result = imap_perform(conn, &connected, dophase_done);
|
|
||||||
|
|
||||||
/* Perform post DO phase operations if necessary */
|
|
||||||
if(!result && *dophase_done)
|
|
||||||
result = imap_dophase_done(conn, connected);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CURLcode imap_setup_connection(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
|
|
||||||
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
|
|
||||||
/* Unless we have asked to tunnel IMAP operations through the proxy, we
|
|
||||||
switch and use HTTP operations only */
|
|
||||||
#ifndef CURL_DISABLE_HTTP
|
|
||||||
if(conn->handler == &Curl_handler_imap)
|
|
||||||
conn->handler = &Curl_handler_imap_proxy;
|
|
||||||
else {
|
|
||||||
#ifdef USE_SSL
|
|
||||||
conn->handler = &Curl_handler_imaps_proxy;
|
|
||||||
#else
|
|
||||||
failf(data, "IMAPS not supported!");
|
|
||||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We explicitly mark this connection as persistent here as we're doing
|
|
||||||
IMAP over HTTP and thus we accidentally avoid setting this value
|
|
||||||
otherwise */
|
|
||||||
conn->bits.close = FALSE;
|
|
||||||
#else
|
|
||||||
failf(data, "IMAP over http proxy requires HTTP support built-in!");
|
|
||||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
data->state.path++; /* don't include the initial slash */
|
|
||||||
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CURL_DISABLE_IMAP */
|
#endif /* CURL_DISABLE_IMAP */
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ struct imap_conn {
|
|||||||
imapstate state; /* Always use imap.c:state() to change state! */
|
imapstate state; /* Always use imap.c:state() to change state! */
|
||||||
bool ssldone; /* Is connect() over SSL done? */
|
bool ssldone; /* Is connect() over SSL done? */
|
||||||
unsigned int authmechs; /* Accepted authentication mechanisms */
|
unsigned int authmechs; /* Accepted authentication mechanisms */
|
||||||
|
unsigned int prefmech; /* Preferred authentication mechanism */
|
||||||
unsigned int authused; /* Auth mechanism used for the connection */
|
unsigned int authused; /* Auth mechanism used for the connection */
|
||||||
int cmdid; /* Last used command ID */
|
int cmdid; /* Last used command ID */
|
||||||
char resptag[5]; /* Response tag to wait for */
|
char resptag[5]; /* Response tag to wait for */
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -239,32 +239,6 @@ char *curl_dostrdup(const char *str, int line, const char *source)
|
|||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
|
|
||||||
{
|
|
||||||
wchar_t *mem;
|
|
||||||
size_t wsiz, bsiz;
|
|
||||||
|
|
||||||
assert(str != NULL);
|
|
||||||
|
|
||||||
if(countcheck("wcsdup", line, source))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
wsiz = wcslen(str) + 1;
|
|
||||||
bsiz = wsiz * sizeof(wchar_t);
|
|
||||||
|
|
||||||
mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
|
|
||||||
if(mem)
|
|
||||||
memcpy(mem, str, bsiz);
|
|
||||||
|
|
||||||
if(source)
|
|
||||||
curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
|
|
||||||
source, line, str, bsiz, mem);
|
|
||||||
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We provide a realloc() that accepts a NULL as pointer, which then
|
/* We provide a realloc() that accepts a NULL as pointer, which then
|
||||||
performs a malloc(). In order to work with ares. */
|
performs a malloc(). In order to work with ares. */
|
||||||
void *curl_dorealloc(void *ptr, size_t wantedsize,
|
void *curl_dorealloc(void *ptr, size_t wantedsize,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -46,11 +46,6 @@ CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
|
|||||||
const char *source);
|
const char *source);
|
||||||
CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
|
CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
|
||||||
CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
|
CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
|
||||||
#ifdef WIN32
|
|
||||||
CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
|
|
||||||
const char *source);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CURL_EXTERN void curl_memdebug(const char *logname);
|
CURL_EXTERN void curl_memdebug(const char *logname);
|
||||||
CURL_EXTERN void curl_memlimit(long limit);
|
CURL_EXTERN void curl_memlimit(long limit);
|
||||||
CURL_EXTERN void curl_memlog(const char *format, ...);
|
CURL_EXTERN void curl_memlog(const char *format, ...);
|
||||||
@@ -89,19 +84,6 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
|
|||||||
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
|
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
|
||||||
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
|
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
# undef wcsdup
|
|
||||||
# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
|
|
||||||
# undef _wcsdup
|
|
||||||
# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
|
|
||||||
# undef _tcsdup
|
|
||||||
# ifdef UNICODE
|
|
||||||
# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
|
|
||||||
# else
|
|
||||||
# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define socket(domain,type,protocol)\
|
#define socket(domain,type,protocol)\
|
||||||
curl_socket(domain,type,protocol,__LINE__,__FILE__)
|
curl_socket(domain,type,protocol,__LINE__,__FILE__)
|
||||||
#undef accept /* for those with accept as a macro */
|
#undef accept /* for those with accept as a macro */
|
||||||
|
|||||||
91
lib/multi.c
91
lib/multi.c
@@ -58,6 +58,7 @@
|
|||||||
#define CURL_SOCKET_HASH_TABLE_SIZE 911
|
#define CURL_SOCKET_HASH_TABLE_SIZE 911
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CURL_CONNECTION_HASH_SIZE 97
|
||||||
|
|
||||||
#define CURL_MULTI_HANDLE 0x000bab1e
|
#define CURL_MULTI_HANDLE 0x000bab1e
|
||||||
|
|
||||||
@@ -75,6 +76,8 @@ static bool isHandleAtHead(struct SessionHandle *handle,
|
|||||||
static CURLMcode add_next_timeout(struct timeval now,
|
static CURLMcode add_next_timeout(struct timeval now,
|
||||||
struct Curl_multi *multi,
|
struct Curl_multi *multi,
|
||||||
struct SessionHandle *d);
|
struct SessionHandle *d);
|
||||||
|
static CURLMcode multi_timeout(struct Curl_multi *multi,
|
||||||
|
long *timeout_ms);
|
||||||
|
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
static const char * const statename[]={
|
static const char * const statename[]={
|
||||||
@@ -246,9 +249,9 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
|
|||||||
* per call."
|
* per call."
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static struct curl_hash *sh_init(void)
|
static struct curl_hash *sh_init(int hashsize)
|
||||||
{
|
{
|
||||||
return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
|
return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
|
||||||
sh_freeentry);
|
sh_freeentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +281,8 @@ static void multi_freeamsg(void *a, void *b)
|
|||||||
(void)b;
|
(void)b;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLM *curl_multi_init(void)
|
struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
|
||||||
|
int chashsize) /* connection hash */
|
||||||
{
|
{
|
||||||
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
|
struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
|
||||||
|
|
||||||
@@ -291,11 +295,11 @@ CURLM *curl_multi_init(void)
|
|||||||
if(!multi->hostcache)
|
if(!multi->hostcache)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
multi->sockhash = sh_init();
|
multi->sockhash = sh_init(hashsize);
|
||||||
if(!multi->sockhash)
|
if(!multi->sockhash)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
multi->conn_cache = Curl_conncache_init();
|
multi->conn_cache = Curl_conncache_init(chashsize);
|
||||||
if(!multi->conn_cache)
|
if(!multi->conn_cache)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@@ -325,6 +329,13 @@ CURLM *curl_multi_init(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CURLM *curl_multi_init(void)
|
||||||
|
{
|
||||||
|
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
|
||||||
|
CURL_CONNECTION_HASH_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||||
CURL *easy_handle)
|
CURL *easy_handle)
|
||||||
{
|
{
|
||||||
@@ -801,10 +812,18 @@ CURLMcode curl_multi_wait(CURLM *multi_handle,
|
|||||||
unsigned int nfds = 0;
|
unsigned int nfds = 0;
|
||||||
unsigned int curlfds;
|
unsigned int curlfds;
|
||||||
struct pollfd *ufds = NULL;
|
struct pollfd *ufds = NULL;
|
||||||
|
long timeout_internal;
|
||||||
|
|
||||||
if(!GOOD_MULTI_HANDLE(multi))
|
if(!GOOD_MULTI_HANDLE(multi))
|
||||||
return CURLM_BAD_HANDLE;
|
return CURLM_BAD_HANDLE;
|
||||||
|
|
||||||
|
/* If the internally desired timeout is actually shorter than requested from
|
||||||
|
the outside, then use the shorter time! But only if the internal timer
|
||||||
|
is actually larger than 0! */
|
||||||
|
(void)multi_timeout(multi, &timeout_internal);
|
||||||
|
if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms))
|
||||||
|
timeout_ms = (int)timeout_internal;
|
||||||
|
|
||||||
/* Count up how many fds we have from the multi handle */
|
/* Count up how many fds we have from the multi handle */
|
||||||
easy=multi->easy.next;
|
easy=multi->easy.next;
|
||||||
while(easy != &multi->easy) {
|
while(easy != &multi->easy) {
|
||||||
@@ -1520,7 +1539,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
else
|
else
|
||||||
follow = FOLLOW_RETRY;
|
follow = FOLLOW_RETRY;
|
||||||
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
easy->result = Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
|
||||||
if(easy->result == CURLE_OK)
|
if(CURLE_OK == easy->result) {
|
||||||
easy->result = Curl_follow(data, newurl, follow);
|
easy->result = Curl_follow(data, newurl, follow);
|
||||||
if(CURLE_OK == easy->result) {
|
if(CURLE_OK == easy->result) {
|
||||||
multistate(easy, CURLM_STATE_CONNECT);
|
multistate(easy, CURLM_STATE_CONNECT);
|
||||||
@@ -1530,6 +1549,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
here */
|
here */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* after the transfer is done, go DONE */
|
/* after the transfer is done, go DONE */
|
||||||
|
|
||||||
@@ -2031,6 +2051,39 @@ static void singlesocket(struct Curl_multi *multi,
|
|||||||
easy->numsocks = num;
|
easy->numsocks = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_multi_closed()
|
||||||
|
*
|
||||||
|
* Used by the connect code to tell the multi_socket code that one of the
|
||||||
|
* sockets we were using have just been closed. This function will then
|
||||||
|
* remove it from the sockethash for this handle to make the multi_socket API
|
||||||
|
* behave properly, especially for the case when libcurl will create another
|
||||||
|
* socket again and it gets the same file descriptor number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
|
||||||
|
{
|
||||||
|
struct Curl_multi *multi = conn->data->multi;
|
||||||
|
if(multi) {
|
||||||
|
/* this is set if this connection is part of a handle that is added to
|
||||||
|
a multi handle, and only then this is necessary */
|
||||||
|
struct Curl_sh_entry *entry =
|
||||||
|
Curl_hash_pick(multi->sockhash, (char *)&s, sizeof(s));
|
||||||
|
|
||||||
|
if(entry) {
|
||||||
|
if(multi->socket_cb)
|
||||||
|
multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
|
||||||
|
multi->socket_userp,
|
||||||
|
entry->socketp);
|
||||||
|
|
||||||
|
/* now remove it from the socket hash */
|
||||||
|
sh_delentry(multi->sockhash, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add_next_timeout()
|
* add_next_timeout()
|
||||||
*
|
*
|
||||||
@@ -2086,6 +2139,11 @@ static CURLMcode add_next_timeout(struct timeval now,
|
|||||||
return CURLM_OK;
|
return CURLM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define TIMEOUT_INACCURACY 40000
|
||||||
|
#else
|
||||||
|
#define TIMEOUT_INACCURACY 3000
|
||||||
|
#endif
|
||||||
|
|
||||||
static CURLMcode multi_socket(struct Curl_multi *multi,
|
static CURLMcode multi_socket(struct Curl_multi *multi,
|
||||||
bool checkall,
|
bool checkall,
|
||||||
@@ -2175,8 +2233,25 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
now.tv_usec += 40000; /* compensate for bad precision timers that might've
|
/* Compensate for bad precision timers that might've triggered too early.
|
||||||
triggered too early */
|
|
||||||
|
This precaution was added in commit 2c72732ebf3da5e as a result of bad
|
||||||
|
resolution in the windows function use(d).
|
||||||
|
|
||||||
|
The problematic case here is when using the multi_socket API and libcurl
|
||||||
|
has told the application about a timeout, and that timeout is what fires
|
||||||
|
off a bit early. As we don't have any IDs associated with the timeout we
|
||||||
|
can't tell which timeout that fired off but we only have the times to use
|
||||||
|
to check what to do. If it fires off too early, we don't run the correct
|
||||||
|
actions and we don't tell the application again about the same timeout as
|
||||||
|
was already first in the queue...
|
||||||
|
|
||||||
|
Originally we made the timeouts run 40 milliseconds early on all systems,
|
||||||
|
but now we have an #ifdef setup to provide a decent precaution inaccuracy
|
||||||
|
margin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
now.tv_usec += TIMEOUT_INACCURACY;
|
||||||
if(now.tv_usec >= 1000000) {
|
if(now.tv_usec >= 1000000) {
|
||||||
now.tv_sec++;
|
now.tv_sec++;
|
||||||
now.tv_usec -= 1000000;
|
now.tv_usec -= 1000000;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes for library-wide functions provided by multi.c
|
* Prototypes for library-wide functions provided by multi.c
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +32,10 @@ void Curl_expire(struct SessionHandle *data, long milli);
|
|||||||
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
|
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
|
||||||
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
||||||
|
|
||||||
|
/* Internal version of curl_multi_init() accepts size parameters for the
|
||||||
|
socket and connection hashes */
|
||||||
|
struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
|
||||||
|
|
||||||
/* the write bits start at bit 16 for the *getsock() bitmap */
|
/* the write bits start at bit 16 for the *getsock() bitmap */
|
||||||
#define GETSOCK_WRITEBITSTART 16
|
#define GETSOCK_WRITEBITSTART 16
|
||||||
|
|
||||||
@@ -77,4 +83,16 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
|
|||||||
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
|
/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
|
||||||
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
|
size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_multi_closed()
|
||||||
|
*
|
||||||
|
* Used by the connect code to tell the multi_socket code that one of the
|
||||||
|
* sockets we were using have just been closed. This function will then
|
||||||
|
* remove it from the sockethash for this handle to make the multi_socket API
|
||||||
|
* behave properly, especially for the case when libcurl will create another
|
||||||
|
* socket again and it gets the same file descriptor number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
|
||||||
|
|
||||||
#endif /* HEADER_CURL_MULTIIF_H */
|
#endif /* HEADER_CURL_MULTIIF_H */
|
||||||
|
|||||||
11
lib/nss.c
11
lib/nss.c
@@ -1482,10 +1482,8 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */
|
|||||||
size_t len, /* amount to write */
|
size_t len, /* amount to write */
|
||||||
CURLcode *curlcode)
|
CURLcode *curlcode)
|
||||||
{
|
{
|
||||||
int rc;
|
ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
|
||||||
|
PR_INTERVAL_NO_WAIT);
|
||||||
rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, -1);
|
|
||||||
|
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
PRInt32 err = PR_GetError();
|
PRInt32 err = PR_GetError();
|
||||||
if(err == PR_WOULD_BLOCK_ERROR)
|
if(err == PR_WOULD_BLOCK_ERROR)
|
||||||
@@ -1513,9 +1511,8 @@ static ssize_t nss_recv(struct connectdata * conn, /* connection data */
|
|||||||
size_t buffersize, /* max amount to read */
|
size_t buffersize, /* max amount to read */
|
||||||
CURLcode *curlcode)
|
CURLcode *curlcode)
|
||||||
{
|
{
|
||||||
ssize_t nread;
|
ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
|
||||||
|
PR_INTERVAL_NO_WAIT);
|
||||||
nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, -1);
|
|
||||||
if(nread < 0) {
|
if(nread < 0) {
|
||||||
/* failed SSL read */
|
/* failed SSL read */
|
||||||
PRInt32 err = PR_GetError();
|
PRInt32 err = PR_GetError();
|
||||||
|
|||||||
451
lib/pop3.c
451
lib/pop3.c
@@ -90,8 +90,6 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/* Local API functions */
|
/* Local API functions */
|
||||||
static CURLcode pop3_parse_url_path(struct connectdata *conn);
|
|
||||||
static CURLcode pop3_parse_custom_request(struct connectdata *conn);
|
|
||||||
static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
|
static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *done);
|
||||||
static CURLcode pop3_do(struct connectdata *conn, bool *done);
|
static CURLcode pop3_do(struct connectdata *conn, bool *done);
|
||||||
static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
|
static CURLcode pop3_done(struct connectdata *conn, CURLcode status,
|
||||||
@@ -103,6 +101,9 @@ static int pop3_getsock(struct connectdata *conn, curl_socket_t *socks,
|
|||||||
int numsocks);
|
int numsocks);
|
||||||
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
|
static CURLcode pop3_doing(struct connectdata *conn, bool *dophase_done);
|
||||||
static CURLcode pop3_setup_connection(struct connectdata *conn);
|
static CURLcode pop3_setup_connection(struct connectdata *conn);
|
||||||
|
static CURLcode pop3_parse_url_options(struct connectdata *conn);
|
||||||
|
static CURLcode pop3_parse_url_path(struct connectdata *conn);
|
||||||
|
static CURLcode pop3_parse_custom_request(struct connectdata *conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* POP3 protocol handler.
|
* POP3 protocol handler.
|
||||||
@@ -216,10 +217,15 @@ static void pop3_to_pop3s(struct connectdata *conn)
|
|||||||
#define pop3_to_pop3s(x) Curl_nop_stmt
|
#define pop3_to_pop3s(x) Curl_nop_stmt
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Function that checks for an ending POP3 status code at the start of the
|
/***********************************************************************
|
||||||
given string, but also detects the APOP timestamp from the server greeting
|
*
|
||||||
and various capabilities from the CAPA response including the supported
|
* pop3_endofresp()
|
||||||
authentication types and allowed SASL mechanisms. */
|
*
|
||||||
|
* Checks for an ending POP3 status code at the start of the given string, but
|
||||||
|
* also detects the APOP timestamp from the server greeting and various
|
||||||
|
* capabilities from the CAPA response including the supported authentication
|
||||||
|
* types and allowed SASL mechanisms.
|
||||||
|
*/
|
||||||
static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
|
static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||||
int *resp)
|
int *resp)
|
||||||
{
|
{
|
||||||
@@ -340,7 +346,12 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
|
|||||||
return FALSE; /* Nothing for us */
|
return FALSE; /* Nothing for us */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the ONLY way to change POP3 state! */
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* state()
|
||||||
|
*
|
||||||
|
* This is the ONLY way to change POP3 state!
|
||||||
|
*/
|
||||||
static void state(struct connectdata *conn, pop3state newstate)
|
static void state(struct connectdata *conn, pop3state newstate)
|
||||||
{
|
{
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
@@ -377,7 +388,14 @@ static void state(struct connectdata *conn, pop3state newstate)
|
|||||||
pop3c->state = newstate;
|
pop3c->state = newstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode pop3_state_capa(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_capa()
|
||||||
|
*
|
||||||
|
* Sends the CAPA command in order to obtain a list of server side supported
|
||||||
|
* capabilities.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_capa(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
@@ -395,7 +413,13 @@ static CURLcode pop3_state_capa(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode pop3_state_starttls(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_starttls()
|
||||||
|
*
|
||||||
|
* Sends the STLS command to start the upgrade to TLS.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_starttls(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
@@ -408,7 +432,13 @@ static CURLcode pop3_state_starttls(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode pop3_state_upgrade_tls(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_upgrade_tls()
|
||||||
|
*
|
||||||
|
* Performs the upgrade to TLS.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_upgrade_tls(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
@@ -422,14 +452,20 @@ static CURLcode pop3_state_upgrade_tls(struct connectdata *conn)
|
|||||||
|
|
||||||
if(pop3c->ssldone) {
|
if(pop3c->ssldone) {
|
||||||
pop3_to_pop3s(conn);
|
pop3_to_pop3s(conn);
|
||||||
result = pop3_state_capa(conn);
|
result = pop3_perform_capa(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode pop3_state_user(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_user()
|
||||||
|
*
|
||||||
|
* Sends a clear text USER command to authenticate with.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_user(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
@@ -451,7 +487,13 @@ static CURLcode pop3_state_user(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
static CURLcode pop3_state_apop(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_apop()
|
||||||
|
*
|
||||||
|
* Sends an APOP command to authenticate with.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_apop(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
@@ -495,12 +537,26 @@ static CURLcode pop3_state_apop(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static CURLcode pop3_authenticate(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_authenticate()
|
||||||
|
*
|
||||||
|
* Sends an AUTH command allowing the client to login with the appropriate
|
||||||
|
* SASL authentication mechanism.
|
||||||
|
*
|
||||||
|
* Additionally, the function will perform fallback to APOP and USER commands
|
||||||
|
* should a common mechanism not be available between the client and server.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_authenticate(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
const char *mech = NULL;
|
const char *mech = NULL;
|
||||||
pop3state authstate = POP3_STOP;
|
char *initresp = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
pop3state state1 = POP3_STOP;
|
||||||
|
pop3state state2 = POP3_STOP;
|
||||||
|
|
||||||
/* Check we have a username and password to authenticate with and end the
|
/* Check we have a username and password to authenticate with and end the
|
||||||
connect phase if we don't */
|
connect phase if we don't */
|
||||||
@@ -514,58 +570,154 @@ static CURLcode pop3_authenticate(struct connectdata *conn)
|
|||||||
security */
|
security */
|
||||||
if(pop3c->authtypes & POP3_TYPE_SASL) {
|
if(pop3c->authtypes & POP3_TYPE_SASL) {
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
if(pop3c->authmechs & SASL_MECH_DIGEST_MD5) {
|
if((pop3c->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||||
|
(pop3c->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||||
mech = "DIGEST-MD5";
|
mech = "DIGEST-MD5";
|
||||||
authstate = POP3_AUTH_DIGESTMD5;
|
state1 = POP3_AUTH_DIGESTMD5;
|
||||||
pop3c->authused = SASL_MECH_DIGEST_MD5;
|
pop3c->authused = SASL_MECH_DIGEST_MD5;
|
||||||
}
|
}
|
||||||
else if(pop3c->authmechs & SASL_MECH_CRAM_MD5) {
|
else if((pop3c->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||||
|
(pop3c->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||||
mech = "CRAM-MD5";
|
mech = "CRAM-MD5";
|
||||||
authstate = POP3_AUTH_CRAMMD5;
|
state1 = POP3_AUTH_CRAMMD5;
|
||||||
pop3c->authused = SASL_MECH_CRAM_MD5;
|
pop3c->authused = SASL_MECH_CRAM_MD5;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NTLM
|
#ifdef USE_NTLM
|
||||||
if(pop3c->authmechs & SASL_MECH_NTLM) {
|
if((pop3c->authmechs & SASL_MECH_NTLM) &&
|
||||||
|
(pop3c->prefmech & SASL_MECH_NTLM)) {
|
||||||
mech = "NTLM";
|
mech = "NTLM";
|
||||||
authstate = POP3_AUTH_NTLM;
|
state1 = POP3_AUTH_NTLM;
|
||||||
|
state2 = POP3_AUTH_NTLM_TYPE2MSG;
|
||||||
pop3c->authused = SASL_MECH_NTLM;
|
pop3c->authused = SASL_MECH_NTLM;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
|
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||||
|
&conn->ntlm,
|
||||||
|
&initresp, &len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(pop3c->authmechs & SASL_MECH_LOGIN) {
|
if((pop3c->authmechs & SASL_MECH_LOGIN) &&
|
||||||
|
(pop3c->prefmech & SASL_MECH_LOGIN)) {
|
||||||
mech = "LOGIN";
|
mech = "LOGIN";
|
||||||
authstate = POP3_AUTH_LOGIN;
|
state1 = POP3_AUTH_LOGIN;
|
||||||
|
state2 = POP3_AUTH_LOGIN_PASSWD;
|
||||||
pop3c->authused = SASL_MECH_LOGIN;
|
pop3c->authused = SASL_MECH_LOGIN;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
|
result = Curl_sasl_create_login_message(conn->data, conn->user,
|
||||||
|
&initresp, &len);
|
||||||
}
|
}
|
||||||
else if(pop3c->authmechs & SASL_MECH_PLAIN) {
|
else if((pop3c->authmechs & SASL_MECH_PLAIN) &&
|
||||||
|
(pop3c->prefmech & SASL_MECH_PLAIN)) {
|
||||||
mech = "PLAIN";
|
mech = "PLAIN";
|
||||||
authstate = POP3_AUTH_PLAIN;
|
state1 = POP3_AUTH_PLAIN;
|
||||||
|
state2 = POP3_AUTH_FINAL;
|
||||||
pop3c->authused = SASL_MECH_PLAIN;
|
pop3c->authused = SASL_MECH_PLAIN;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
|
result = Curl_sasl_create_plain_message(conn->data, conn->user,
|
||||||
|
conn->passwd, &initresp,
|
||||||
|
&len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mech) {
|
if(!result) {
|
||||||
|
if(mech && (pop3c->preftype & POP3_TYPE_SASL)) {
|
||||||
/* Perform SASL based authentication */
|
/* Perform SASL based authentication */
|
||||||
|
if(initresp &&
|
||||||
|
8 + strlen(mech) + len <= 255) { /* AUTH <mech> ...<crlf> */
|
||||||
|
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s %s", mech, initresp);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, state2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
|
result = Curl_pp_sendf(&pop3c->pp, "AUTH %s", mech);
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
state(conn, authstate);
|
state(conn, state1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(initresp);
|
||||||
}
|
}
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
else if(pop3c->authtypes & POP3_TYPE_APOP)
|
else if((pop3c->authtypes & POP3_TYPE_APOP) &&
|
||||||
|
(pop3c->preftype & POP3_TYPE_APOP))
|
||||||
/* Perform APOP authentication */
|
/* Perform APOP authentication */
|
||||||
result = pop3_state_apop(conn);
|
result = pop3_perform_apop(conn);
|
||||||
#endif
|
#endif
|
||||||
else if(pop3c->authtypes & POP3_TYPE_CLEARTEXT)
|
else if((pop3c->authtypes & POP3_TYPE_CLEARTEXT) &&
|
||||||
|
(pop3c->preftype & POP3_TYPE_CLEARTEXT))
|
||||||
/* Perform clear text authentication */
|
/* Perform clear text authentication */
|
||||||
result = pop3_state_user(conn);
|
result = pop3_perform_user(conn);
|
||||||
else {
|
else {
|
||||||
/* Other mechanisms not supported */
|
/* Other mechanisms not supported */
|
||||||
infof(conn->data, "No known authentication mechanisms supported!\n");
|
infof(conn->data, "No known authentication mechanisms supported!\n");
|
||||||
result = CURLE_LOGIN_DENIED;
|
result = CURLE_LOGIN_DENIED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_command()
|
||||||
|
*
|
||||||
|
* Sends a POP3 based command.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_command(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct POP3 *pop3 = data->state.proto.pop3;
|
||||||
|
const char *command = NULL;
|
||||||
|
|
||||||
|
/* Calculate the default command */
|
||||||
|
if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
|
||||||
|
command = "LIST";
|
||||||
|
|
||||||
|
if(pop3->id[0] != '\0')
|
||||||
|
/* Message specific LIST so skip the BODY transfer */
|
||||||
|
pop3->transfer = FTPTRANSFER_INFO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
command = "RETR";
|
||||||
|
|
||||||
|
/* Send the command */
|
||||||
|
if(pop3->id[0] != '\0')
|
||||||
|
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
|
||||||
|
(pop3->custom && pop3->custom[0] != '\0' ?
|
||||||
|
pop3->custom : command), pop3->id);
|
||||||
|
else
|
||||||
|
result = Curl_pp_sendf(&conn->proto.pop3c.pp,
|
||||||
|
(pop3->custom && pop3->custom[0] != '\0' ?
|
||||||
|
pop3->custom : command));
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, POP3_COMMAND);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_perform_quit()
|
||||||
|
*
|
||||||
|
* Performs the quit action prior to sclose() be called.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_perform_quit(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
|
/* Send the QUIT command */
|
||||||
|
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, POP3_QUIT);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -582,10 +734,10 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
|
|||||||
|
|
||||||
if(pop3code != '+') {
|
if(pop3code != '+') {
|
||||||
failf(data, "Got unexpected pop3-server response");
|
failf(data, "Got unexpected pop3-server response");
|
||||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
result = CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
result = pop3_state_capa(conn);
|
result = pop3_perform_capa(conn);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -601,22 +753,22 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
|
|||||||
(void)instate; /* no use for this yet */
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
if(pop3code != '+')
|
if(pop3code != '+')
|
||||||
result = pop3_state_user(conn);
|
result = pop3_perform_user(conn);
|
||||||
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||||
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
||||||
if(pop3c->tls_supported)
|
if(pop3c->tls_supported)
|
||||||
/* Switch to TLS connection now */
|
/* Switch to TLS connection now */
|
||||||
result = pop3_state_starttls(conn);
|
result = pop3_perform_starttls(conn);
|
||||||
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
||||||
/* Fallback and carry on with authentication */
|
/* Fallback and carry on with authentication */
|
||||||
result = pop3_authenticate(conn);
|
result = pop3_perform_authenticate(conn);
|
||||||
else {
|
else {
|
||||||
failf(data, "STLS not supported.");
|
failf(data, "STLS not supported.");
|
||||||
result = CURLE_USE_SSL_FAILED;
|
result = CURLE_USE_SSL_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = pop3_authenticate(conn);
|
result = pop3_perform_authenticate(conn);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -637,15 +789,15 @@ static CURLcode pop3_state_starttls_resp(struct connectdata *conn,
|
|||||||
result = CURLE_USE_SSL_FAILED;
|
result = CURLE_USE_SSL_FAILED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = pop3_authenticate(conn);
|
result = pop3_perform_authenticate(conn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = pop3_state_upgrade_tls(conn);
|
result = pop3_perform_upgrade_tls(conn);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For AUTH PLAIN responses */
|
/* For AUTH PLAIN (without initial response) responses */
|
||||||
static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
|
static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
|
||||||
int pop3code,
|
int pop3code,
|
||||||
pop3state instate)
|
pop3state instate)
|
||||||
@@ -682,7 +834,7 @@ static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For AUTH LOGIN responses */
|
/* For AUTH LOGIN (without initial response) responses */
|
||||||
static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
|
static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
|
||||||
int pop3code,
|
int pop3code,
|
||||||
pop3state instate)
|
pop3state instate)
|
||||||
@@ -879,7 +1031,7 @@ static CURLcode pop3_state_auth_digest_resp_resp(struct connectdata *conn,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_NTLM
|
#ifdef USE_NTLM
|
||||||
/* For AUTH NTLM responses */
|
/* For AUTH NTLM (without initial response) responses */
|
||||||
static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
|
static CURLcode pop3_state_auth_ntlm_resp(struct connectdata *conn,
|
||||||
int pop3code,
|
int pop3code,
|
||||||
pop3state instate)
|
pop3state instate)
|
||||||
@@ -980,6 +1132,7 @@ static CURLcode pop3_state_auth_final_resp(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
|
/* For APOP responses */
|
||||||
static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
|
static CURLcode pop3_state_apop_resp(struct connectdata *conn, int pop3code,
|
||||||
pop3state instate)
|
pop3state instate)
|
||||||
{
|
{
|
||||||
@@ -1043,41 +1196,6 @@ static CURLcode pop3_state_pass_resp(struct connectdata *conn, int pop3code,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the DO phase for the command */
|
|
||||||
static CURLcode pop3_command(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct POP3 *pop3 = data->state.proto.pop3;
|
|
||||||
const char *command = NULL;
|
|
||||||
|
|
||||||
/* Calculate the default command */
|
|
||||||
if(pop3->id[0] == '\0' || conn->data->set.ftp_list_only) {
|
|
||||||
command = "LIST";
|
|
||||||
|
|
||||||
if(pop3->id[0] != '\0')
|
|
||||||
/* Message specific LIST so skip the BODY transfer */
|
|
||||||
pop3->transfer = FTPTRANSFER_INFO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
command = "RETR";
|
|
||||||
|
|
||||||
/* Send the command */
|
|
||||||
if(pop3->id[0] != '\0')
|
|
||||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "%s %s",
|
|
||||||
(pop3->custom && pop3->custom[0] != '\0' ?
|
|
||||||
pop3->custom : command), pop3->id);
|
|
||||||
else
|
|
||||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp,
|
|
||||||
(pop3->custom && pop3->custom[0] != '\0' ?
|
|
||||||
pop3->custom : command));
|
|
||||||
|
|
||||||
if(!result)
|
|
||||||
state(conn, POP3_COMMAND);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For command responses */
|
/* For command responses */
|
||||||
static CURLcode pop3_state_command_resp(struct connectdata *conn,
|
static CURLcode pop3_state_command_resp(struct connectdata *conn,
|
||||||
int pop3code,
|
int pop3code,
|
||||||
@@ -1146,7 +1264,7 @@ static CURLcode pop3_statemach_act(struct connectdata *conn)
|
|||||||
|
|
||||||
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
|
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */
|
||||||
if(pop3c->state == POP3_UPGRADETLS)
|
if(pop3c->state == POP3_UPGRADETLS)
|
||||||
return pop3_state_upgrade_tls(conn);
|
return pop3_perform_upgrade_tls(conn);
|
||||||
|
|
||||||
/* Flush any data that needs to be sent */
|
/* Flush any data that needs to be sent */
|
||||||
if(pp->sendleft)
|
if(pp->sendleft)
|
||||||
@@ -1332,9 +1450,18 @@ static CURLcode pop3_connect(struct connectdata *conn, bool *done)
|
|||||||
pp->endofresp = pop3_endofresp;
|
pp->endofresp = pop3_endofresp;
|
||||||
pp->conn = conn;
|
pp->conn = conn;
|
||||||
|
|
||||||
|
/* Set the default preferred authentication type and mechanism */
|
||||||
|
pop3c->preftype = POP3_TYPE_ANY;
|
||||||
|
pop3c->prefmech = SASL_AUTH_ANY;
|
||||||
|
|
||||||
/* Initialise the pingpong layer */
|
/* Initialise the pingpong layer */
|
||||||
Curl_pp_init(pp);
|
Curl_pp_init(pp);
|
||||||
|
|
||||||
|
/* Parse the URL options */
|
||||||
|
result = pop3_parse_url_options(conn);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
|
||||||
/* Start off waiting for the server greeting response */
|
/* Start off waiting for the server greeting response */
|
||||||
state(conn, POP3_SERVERGREET);
|
state(conn, POP3_SERVERGREET);
|
||||||
|
|
||||||
@@ -1407,7 +1534,7 @@ static CURLcode pop3_perform(struct connectdata *conn, bool *connected,
|
|||||||
*dophase_done = FALSE; /* not done yet */
|
*dophase_done = FALSE; /* not done yet */
|
||||||
|
|
||||||
/* Start the first command in the DO phase */
|
/* Start the first command in the DO phase */
|
||||||
result = pop3_command(conn);
|
result = pop3_perform_command(conn);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1461,25 +1588,6 @@ static CURLcode pop3_do(struct connectdata *conn, bool *done)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
* pop3_quit()
|
|
||||||
*
|
|
||||||
* Performs the quit action prior to sclose() be called.
|
|
||||||
*/
|
|
||||||
static CURLcode pop3_quit(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
|
|
||||||
/* Send the QUIT command */
|
|
||||||
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "QUIT");
|
|
||||||
|
|
||||||
if(!result)
|
|
||||||
state(conn, POP3_QUIT);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* pop3_disconnect()
|
* pop3_disconnect()
|
||||||
@@ -1499,7 +1607,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn,
|
|||||||
/* The POP3 session may or may not have been allocated/setup at this
|
/* The POP3 session may or may not have been allocated/setup at this
|
||||||
point! */
|
point! */
|
||||||
if(!dead_connection && pop3c->pp.conn)
|
if(!dead_connection && pop3c->pp.conn)
|
||||||
if(!pop3_quit(conn))
|
if(!pop3_perform_quit(conn))
|
||||||
(void)pop3_block_statemach(conn); /* ignore errors on QUIT */
|
(void)pop3_block_statemach(conn); /* ignore errors on QUIT */
|
||||||
|
|
||||||
/* Disconnect from the server */
|
/* Disconnect from the server */
|
||||||
@@ -1514,37 +1622,6 @@ static CURLcode pop3_disconnect(struct connectdata *conn,
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
* pop3_parse_url_path()
|
|
||||||
*
|
|
||||||
* Parse the URL path into separate path components.
|
|
||||||
*/
|
|
||||||
static CURLcode pop3_parse_url_path(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
/* The POP3 struct is already initialised in pop3_connect() */
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct POP3 *pop3 = data->state.proto.pop3;
|
|
||||||
const char *path = data->state.path;
|
|
||||||
|
|
||||||
/* URL decode the path for the message ID */
|
|
||||||
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CURLcode pop3_parse_custom_request(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct POP3 *pop3 = data->state.proto.pop3;
|
|
||||||
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
|
|
||||||
|
|
||||||
/* URL decode the custom request */
|
|
||||||
if(custom)
|
|
||||||
result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call this when the DO phase has completed */
|
/* Call this when the DO phase has completed */
|
||||||
static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
|
static CURLcode pop3_dophase_done(struct connectdata *conn, bool connected)
|
||||||
{
|
{
|
||||||
@@ -1639,8 +1716,116 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function scans the body after the end-of-body and writes everything
|
/***********************************************************************
|
||||||
until the end is found */
|
*
|
||||||
|
* pop3_parse_url_options()
|
||||||
|
*
|
||||||
|
* Parse the URL login options.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_parse_url_options(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||||
|
const char *options = conn->options;
|
||||||
|
const char *ptr = options;
|
||||||
|
|
||||||
|
if(options) {
|
||||||
|
const char *key = ptr;
|
||||||
|
|
||||||
|
while(*ptr && *ptr != '=')
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if(strnequal(key, "AUTH", 4)) {
|
||||||
|
const char *value = ptr + 1;
|
||||||
|
|
||||||
|
if(strequal(value, "*")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_ANY;
|
||||||
|
pop3c->prefmech = SASL_AUTH_ANY;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "+APOP")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_APOP;
|
||||||
|
pop3c->prefmech = SASL_AUTH_NONE;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "LOGIN")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_SASL;
|
||||||
|
pop3c->prefmech = SASL_MECH_LOGIN;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "PLAIN")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_SASL;
|
||||||
|
pop3c->prefmech = SASL_MECH_PLAIN;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "CRAM-MD5")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_SASL;
|
||||||
|
pop3c->prefmech = SASL_MECH_CRAM_MD5;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "DIGEST-MD5")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_SASL;
|
||||||
|
pop3c->prefmech = SASL_MECH_DIGEST_MD5;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "GSSAPI")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_SASL;
|
||||||
|
pop3c->prefmech = SASL_MECH_GSSAPI;
|
||||||
|
}
|
||||||
|
else if(strequal(value, "NTLM")) {
|
||||||
|
pop3c->preftype = POP3_TYPE_SASL;
|
||||||
|
pop3c->prefmech = SASL_MECH_NTLM;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pop3c->preftype = POP3_TYPE_NONE;
|
||||||
|
pop3c->prefmech = SASL_AUTH_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = CURLE_URL_MALFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_parse_url_path()
|
||||||
|
*
|
||||||
|
* Parse the URL path into separate path components.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_parse_url_path(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
/* The POP3 struct is already initialised in pop3_connect() */
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct POP3 *pop3 = data->state.proto.pop3;
|
||||||
|
const char *path = data->state.path;
|
||||||
|
|
||||||
|
/* URL decode the path for the message ID */
|
||||||
|
return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* pop3_parse_custom_request()
|
||||||
|
*
|
||||||
|
* Parse the custom request.
|
||||||
|
*/
|
||||||
|
static CURLcode pop3_parse_custom_request(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct POP3 *pop3 = data->state.proto.pop3;
|
||||||
|
const char *custom = data->set.str[STRING_CUSTOMREQUEST];
|
||||||
|
|
||||||
|
/* URL decode the custom request */
|
||||||
|
if(custom)
|
||||||
|
result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* Curl_pop3_write()
|
||||||
|
*
|
||||||
|
* This function scans the body after the end-of-body and writes everything
|
||||||
|
* until the end is found.
|
||||||
|
*/
|
||||||
CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
|
CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
|
||||||
{
|
{
|
||||||
/* This code could be made into a special function in the handler struct */
|
/* This code could be made into a special function in the handler struct */
|
||||||
|
|||||||
14
lib/pop3.h
14
lib/pop3.h
@@ -72,8 +72,10 @@ struct pop3_conn {
|
|||||||
have been received so far */
|
have been received so far */
|
||||||
size_t strip; /* Number of bytes from the start to ignore as
|
size_t strip; /* Number of bytes from the start to ignore as
|
||||||
non-body */
|
non-body */
|
||||||
unsigned int authtypes; /* Supported authentication types */
|
unsigned int authtypes; /* Accepted authentication types */
|
||||||
unsigned int authmechs; /* Accepted SASL authentication mechanisms */
|
unsigned int authmechs; /* Accepted SASL authentication mechanisms */
|
||||||
|
unsigned int preftype; /* Preferred authentication type */
|
||||||
|
unsigned int prefmech; /* Preferred SASL authentication mechanism */
|
||||||
unsigned int authused; /* SASL auth mechanism used for the connection */
|
unsigned int authused; /* SASL auth mechanism used for the connection */
|
||||||
char *apoptimestamp; /* APOP timestamp from the server greeting */
|
char *apoptimestamp; /* APOP timestamp from the server greeting */
|
||||||
bool tls_supported; /* StartTLS capability supported by server */
|
bool tls_supported; /* StartTLS capability supported by server */
|
||||||
@@ -83,9 +85,13 @@ extern const struct Curl_handler Curl_handler_pop3;
|
|||||||
extern const struct Curl_handler Curl_handler_pop3s;
|
extern const struct Curl_handler Curl_handler_pop3s;
|
||||||
|
|
||||||
/* Authentication type flags */
|
/* Authentication type flags */
|
||||||
#define POP3_TYPE_CLEARTEXT 0x0001
|
#define POP3_TYPE_CLEARTEXT (1 << 0)
|
||||||
#define POP3_TYPE_APOP 0x0002
|
#define POP3_TYPE_APOP (1 << 1)
|
||||||
#define POP3_TYPE_SASL 0x0004
|
#define POP3_TYPE_SASL (1 << 2)
|
||||||
|
|
||||||
|
/* Authentication type values */
|
||||||
|
#define POP3_TYPE_NONE 0
|
||||||
|
#define POP3_TYPE_ANY ~0
|
||||||
|
|
||||||
/* This is the 5-bytes End-Of-Body marker for POP3 */
|
/* This is the 5-bytes End-Of-Body marker for POP3 */
|
||||||
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
|
#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a"
|
||||||
|
|||||||
535
lib/smtp.c
535
lib/smtp.c
@@ -26,6 +26,7 @@
|
|||||||
* RFC4616 PLAIN authentication
|
* RFC4616 PLAIN authentication
|
||||||
* RFC4954 SMTP Authentication
|
* RFC4954 SMTP Authentication
|
||||||
* RFC5321 SMTP protocol
|
* RFC5321 SMTP protocol
|
||||||
|
* Draft SMTP URL Interface
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@@ -99,6 +100,8 @@ static int smtp_getsock(struct connectdata *conn, curl_socket_t *socks,
|
|||||||
int numsocks);
|
int numsocks);
|
||||||
static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
|
static CURLcode smtp_doing(struct connectdata *conn, bool *dophase_done);
|
||||||
static CURLcode smtp_setup_connection(struct connectdata *conn);
|
static CURLcode smtp_setup_connection(struct connectdata *conn);
|
||||||
|
static CURLcode smtp_parse_url_options(struct connectdata *conn);
|
||||||
|
static CURLcode smtp_parse_url_path(struct connectdata *conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMTP protocol handler.
|
* SMTP protocol handler.
|
||||||
@@ -212,9 +215,14 @@ static void smtp_to_smtps(struct connectdata *conn)
|
|||||||
#define smtp_to_smtps(x) Curl_nop_stmt
|
#define smtp_to_smtps(x) Curl_nop_stmt
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Function that checks for an ending SMTP status code at the start of the
|
/***********************************************************************
|
||||||
given string, but also detects various capabilities from the EHLO response
|
*
|
||||||
including the supported authentication mechanisms. */
|
* pop3_endofresp()
|
||||||
|
*
|
||||||
|
* Checks for an ending SMTP status code at the start of the given string, but
|
||||||
|
* also detects various capabilities from the EHLO response including the
|
||||||
|
* supported authentication mechanisms.
|
||||||
|
*/
|
||||||
static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
|
static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||||
int *resp)
|
int *resp)
|
||||||
{
|
{
|
||||||
@@ -292,7 +300,12 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the ONLY way to change SMTP state! */
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* state()
|
||||||
|
*
|
||||||
|
* This is the ONLY way to change SMTP state!
|
||||||
|
*/
|
||||||
static void state(struct connectdata *conn, smtpstate newstate)
|
static void state(struct connectdata *conn, smtpstate newstate)
|
||||||
{
|
{
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
@@ -330,7 +343,14 @@ static void state(struct connectdata *conn, smtpstate newstate)
|
|||||||
smtpc->state = newstate;
|
smtpc->state = newstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode smtp_state_ehlo(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_ehlo()
|
||||||
|
*
|
||||||
|
* Sends the EHLO command to not only initialise communication with the ESMTP
|
||||||
|
* server but to also obtain a list of server side supported capabilities.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_ehlo(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
@@ -349,7 +369,13 @@ static CURLcode smtp_state_ehlo(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode smtp_state_helo(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_helo()
|
||||||
|
*
|
||||||
|
* Sends the HELO command to initialise communication with the SMTP server.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_helo(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
@@ -366,7 +392,13 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode smtp_state_starttls(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_starttls()
|
||||||
|
*
|
||||||
|
* Sends the STLS command to start the upgrade to TLS.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_starttls(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
@@ -379,7 +411,13 @@ static CURLcode smtp_state_starttls(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode smtp_state_upgrade_tls(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_upgrade_tls()
|
||||||
|
*
|
||||||
|
* Performs the upgrade to TLS.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_upgrade_tls(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
@@ -393,16 +431,24 @@ static CURLcode smtp_state_upgrade_tls(struct connectdata *conn)
|
|||||||
|
|
||||||
if(smtpc->ssldone) {
|
if(smtpc->ssldone) {
|
||||||
smtp_to_smtps(conn);
|
smtp_to_smtps(conn);
|
||||||
result = smtp_state_ehlo(conn);
|
result = smtp_perform_ehlo(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode smtp_authenticate(struct connectdata *conn)
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_authenticate()
|
||||||
|
*
|
||||||
|
* Sends an AUTH command allowing the client to login with the appropriate
|
||||||
|
* SASL authentication mechanism.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_authenticate(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
const char *mech = NULL;
|
const char *mech = NULL;
|
||||||
char *initresp = NULL;
|
char *initresp = NULL;
|
||||||
@@ -421,12 +467,14 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
|
|||||||
/* Calculate the supported authentication mechanism, by decreasing order of
|
/* Calculate the supported authentication mechanism, by decreasing order of
|
||||||
security, as well as the initial response where appropriate */
|
security, as well as the initial response where appropriate */
|
||||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||||
if(smtpc->authmechs & SASL_MECH_DIGEST_MD5) {
|
if((smtpc->authmechs & SASL_MECH_DIGEST_MD5) &&
|
||||||
|
(smtpc->prefmech & SASL_MECH_DIGEST_MD5)) {
|
||||||
mech = "DIGEST-MD5";
|
mech = "DIGEST-MD5";
|
||||||
state1 = SMTP_AUTH_DIGESTMD5;
|
state1 = SMTP_AUTH_DIGESTMD5;
|
||||||
smtpc->authused = SASL_MECH_DIGEST_MD5;
|
smtpc->authused = SASL_MECH_DIGEST_MD5;
|
||||||
}
|
}
|
||||||
else if(smtpc->authmechs & SASL_MECH_CRAM_MD5) {
|
else if((smtpc->authmechs & SASL_MECH_CRAM_MD5) &&
|
||||||
|
(smtpc->prefmech & SASL_MECH_CRAM_MD5)) {
|
||||||
mech = "CRAM-MD5";
|
mech = "CRAM-MD5";
|
||||||
state1 = SMTP_AUTH_CRAMMD5;
|
state1 = SMTP_AUTH_CRAMMD5;
|
||||||
smtpc->authused = SASL_MECH_CRAM_MD5;
|
smtpc->authused = SASL_MECH_CRAM_MD5;
|
||||||
@@ -434,43 +482,48 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NTLM
|
#ifdef USE_NTLM
|
||||||
if(smtpc->authmechs & SASL_MECH_NTLM) {
|
if((smtpc->authmechs & SASL_MECH_NTLM) &&
|
||||||
|
(smtpc->prefmech & SASL_MECH_NTLM)) {
|
||||||
mech = "NTLM";
|
mech = "NTLM";
|
||||||
state1 = SMTP_AUTH_NTLM;
|
state1 = SMTP_AUTH_NTLM;
|
||||||
state2 = SMTP_AUTH_NTLM_TYPE2MSG;
|
state2 = SMTP_AUTH_NTLM_TYPE2MSG;
|
||||||
smtpc->authused = SASL_MECH_NTLM;
|
smtpc->authused = SASL_MECH_NTLM;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
result = Curl_sasl_create_ntlm_type1_message(conn->user, conn->passwd,
|
||||||
&conn->ntlm,
|
&conn->ntlm,
|
||||||
&initresp, &len);
|
&initresp, &len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if(smtpc->authmechs & SASL_MECH_LOGIN) {
|
if((smtpc->authmechs & SASL_MECH_LOGIN) &&
|
||||||
|
(smtpc->prefmech & SASL_MECH_LOGIN)) {
|
||||||
mech = "LOGIN";
|
mech = "LOGIN";
|
||||||
state1 = SMTP_AUTH_LOGIN;
|
state1 = SMTP_AUTH_LOGIN;
|
||||||
state2 = SMTP_AUTH_LOGIN_PASSWD;
|
state2 = SMTP_AUTH_LOGIN_PASSWD;
|
||||||
smtpc->authused = SASL_MECH_LOGIN;
|
smtpc->authused = SASL_MECH_LOGIN;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
result = Curl_sasl_create_login_message(conn->data, conn->user,
|
result = Curl_sasl_create_login_message(conn->data, conn->user,
|
||||||
&initresp, &len);
|
&initresp, &len);
|
||||||
}
|
}
|
||||||
else if(smtpc->authmechs & SASL_MECH_PLAIN) {
|
else if((smtpc->authmechs & SASL_MECH_PLAIN) &&
|
||||||
|
(smtpc->prefmech & SASL_MECH_PLAIN)) {
|
||||||
mech = "PLAIN";
|
mech = "PLAIN";
|
||||||
state1 = SMTP_AUTH_PLAIN;
|
state1 = SMTP_AUTH_PLAIN;
|
||||||
state2 = SMTP_AUTH_FINAL;
|
state2 = SMTP_AUTH_FINAL;
|
||||||
smtpc->authused = SASL_MECH_PLAIN;
|
smtpc->authused = SASL_MECH_PLAIN;
|
||||||
|
|
||||||
|
if(data->set.sasl_ir)
|
||||||
result = Curl_sasl_create_plain_message(conn->data, conn->user,
|
result = Curl_sasl_create_plain_message(conn->data, conn->user,
|
||||||
conn->passwd, &initresp, &len);
|
conn->passwd, &initresp, &len);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* Other mechanisms not supported */
|
|
||||||
infof(conn->data, "No known authentication mechanisms supported!\n");
|
|
||||||
result = CURLE_LOGIN_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!result) {
|
if(!result) {
|
||||||
|
if(mech) {
|
||||||
/* Perform SASL based authentication */
|
/* Perform SASL based authentication */
|
||||||
if(initresp &&
|
if(initresp &&
|
||||||
strlen(mech) + len <= 512 - 8) { /* AUTH <mech> ...<crlf> */
|
8 + strlen(mech) + len <= 512) { /* AUTH <mech> ...<crlf> */
|
||||||
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
|
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
@@ -485,6 +538,136 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
|
|||||||
|
|
||||||
Curl_safefree(initresp);
|
Curl_safefree(initresp);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* Other mechanisms not supported */
|
||||||
|
infof(conn->data, "No known authentication mechanisms supported!\n");
|
||||||
|
result = CURLE_LOGIN_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_mail()
|
||||||
|
*
|
||||||
|
* Sends an MAIL command to initiate the upload of a message.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_mail(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
char *from = NULL;
|
||||||
|
char *auth = NULL;
|
||||||
|
char *size = NULL;
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
|
/* Calculate the FROM parameter */
|
||||||
|
if(!data->set.str[STRING_MAIL_FROM])
|
||||||
|
/* Null reverse-path, RFC-5321, sect. 3.6.3 */
|
||||||
|
from = strdup("<>");
|
||||||
|
else if(data->set.str[STRING_MAIL_FROM][0] == '<')
|
||||||
|
from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
|
||||||
|
else
|
||||||
|
from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
|
||||||
|
|
||||||
|
if(!from)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* Calculate the optional AUTH parameter */
|
||||||
|
if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) {
|
||||||
|
if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
|
||||||
|
auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
|
||||||
|
else
|
||||||
|
/* Empty AUTH, RFC-2554, sect. 5 */
|
||||||
|
auth = strdup("<>");
|
||||||
|
|
||||||
|
if(!auth) {
|
||||||
|
Curl_safefree(from);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the optional SIZE parameter */
|
||||||
|
if(conn->proto.smtpc.size_supported && conn->data->set.infilesize > 0) {
|
||||||
|
size = aprintf("%" FORMAT_OFF_T, data->set.infilesize);
|
||||||
|
|
||||||
|
if(!size) {
|
||||||
|
Curl_safefree(from);
|
||||||
|
Curl_safefree(auth);
|
||||||
|
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the MAIL command */
|
||||||
|
if(!auth && !size)
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
||||||
|
"MAIL FROM:%s", from);
|
||||||
|
else if(auth && !size)
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
||||||
|
"MAIL FROM:%s AUTH=%s", from, auth);
|
||||||
|
else if(auth && size)
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
||||||
|
"MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
|
||||||
|
else
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
||||||
|
"MAIL FROM:%s SIZE=%s", from, size);
|
||||||
|
|
||||||
|
Curl_safefree(from);
|
||||||
|
Curl_safefree(auth);
|
||||||
|
Curl_safefree(size);
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, SMTP_MAIL);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_rcpt_to()
|
||||||
|
*
|
||||||
|
* Sends a RCPT TO command for a given recipient as part of the message upload
|
||||||
|
* process.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_rcpt_to(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct SMTP *smtp = data->state.proto.smtp;
|
||||||
|
|
||||||
|
/* Send the RCPT TO command */
|
||||||
|
if(smtp->rcpt) {
|
||||||
|
if(smtp->rcpt->data[0] == '<')
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
|
||||||
|
smtp->rcpt->data);
|
||||||
|
else
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
|
||||||
|
smtp->rcpt->data);
|
||||||
|
if(!result)
|
||||||
|
state(conn, SMTP_RCPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_perform_quit()
|
||||||
|
*
|
||||||
|
* Performs the quit action prior to sclose() being called.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_perform_quit(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
|
/* Send the QUIT command */
|
||||||
|
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
|
||||||
|
|
||||||
|
if(!result)
|
||||||
|
state(conn, SMTP_QUIT);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -501,10 +684,10 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
|
|||||||
|
|
||||||
if(smtpcode/100 != 2) {
|
if(smtpcode/100 != 2) {
|
||||||
failf(data, "Got unexpected smtp-server response: %d", smtpcode);
|
failf(data, "Got unexpected smtp-server response: %d", smtpcode);
|
||||||
return CURLE_FTP_WEIRD_SERVER_REPLY;
|
result = CURLE_FTP_WEIRD_SERVER_REPLY;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
result = smtp_state_ehlo(conn);
|
result = smtp_perform_ehlo(conn);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -525,10 +708,10 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
|
|||||||
result = CURLE_USE_SSL_FAILED;
|
result = CURLE_USE_SSL_FAILED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = smtp_authenticate(conn);
|
result = smtp_perform_authenticate(conn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = smtp_state_upgrade_tls(conn);
|
result = smtp_perform_upgrade_tls(conn);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -546,7 +729,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
|||||||
if(smtpcode/100 != 2) {
|
if(smtpcode/100 != 2) {
|
||||||
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
|
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
|
||||||
!conn->bits.user_passwd)
|
!conn->bits.user_passwd)
|
||||||
result = smtp_state_helo(conn);
|
result = smtp_perform_helo(conn);
|
||||||
else {
|
else {
|
||||||
failf(data, "Remote access denied: %d", smtpcode);
|
failf(data, "Remote access denied: %d", smtpcode);
|
||||||
result = CURLE_REMOTE_ACCESS_DENIED;
|
result = CURLE_REMOTE_ACCESS_DENIED;
|
||||||
@@ -556,17 +739,17 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
|||||||
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
||||||
if(smtpc->tls_supported)
|
if(smtpc->tls_supported)
|
||||||
/* Switch to TLS connection now */
|
/* Switch to TLS connection now */
|
||||||
result = smtp_state_starttls(conn);
|
result = smtp_perform_starttls(conn);
|
||||||
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
||||||
/* Fallback and carry on with authentication */
|
/* Fallback and carry on with authentication */
|
||||||
result = smtp_authenticate(conn);
|
result = smtp_perform_authenticate(conn);
|
||||||
else {
|
else {
|
||||||
failf(data, "STARTTLS not supported.");
|
failf(data, "STARTTLS not supported.");
|
||||||
result = CURLE_USE_SSL_FAILED;
|
result = CURLE_USE_SSL_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = smtp_authenticate(conn);
|
result = smtp_perform_authenticate(conn);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -926,99 +1109,6 @@ static CURLcode smtp_state_auth_final_resp(struct connectdata *conn,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the DO phase */
|
|
||||||
static CURLcode smtp_mail(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
char *from = NULL;
|
|
||||||
char *auth = NULL;
|
|
||||||
char *size = NULL;
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
|
|
||||||
/* Calculate the FROM parameter */
|
|
||||||
if(!data->set.str[STRING_MAIL_FROM])
|
|
||||||
/* Null reverse-path, RFC-2821, sect. 3.7 */
|
|
||||||
from = strdup("<>");
|
|
||||||
else if(data->set.str[STRING_MAIL_FROM][0] == '<')
|
|
||||||
from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
|
|
||||||
else
|
|
||||||
from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
|
|
||||||
|
|
||||||
if(!from)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
/* Calculate the optional AUTH parameter */
|
|
||||||
if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.authused) {
|
|
||||||
if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
|
|
||||||
auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
|
|
||||||
else
|
|
||||||
/* Empty AUTH, RFC-2554, sect. 5 */
|
|
||||||
auth = strdup("<>");
|
|
||||||
|
|
||||||
if(!auth) {
|
|
||||||
Curl_safefree(from);
|
|
||||||
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate the optional SIZE parameter */
|
|
||||||
if(conn->proto.smtpc.size_supported && conn->data->set.infilesize > 0) {
|
|
||||||
size = aprintf("%" FORMAT_OFF_T, data->set.infilesize);
|
|
||||||
|
|
||||||
if(!size) {
|
|
||||||
Curl_safefree(from);
|
|
||||||
Curl_safefree(auth);
|
|
||||||
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send the MAIL command */
|
|
||||||
if(!auth && !size)
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
|
||||||
"MAIL FROM:%s", from);
|
|
||||||
else if(auth && !size)
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
|
||||||
"MAIL FROM:%s AUTH=%s", from, auth);
|
|
||||||
else if(auth && size)
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
|
||||||
"MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
|
|
||||||
else
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp,
|
|
||||||
"MAIL FROM:%s SIZE=%s", from, size);
|
|
||||||
|
|
||||||
Curl_safefree(from);
|
|
||||||
Curl_safefree(auth);
|
|
||||||
Curl_safefree(size);
|
|
||||||
|
|
||||||
if(!result)
|
|
||||||
state(conn, SMTP_MAIL);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CURLcode smtp_rcpt_to(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
struct SMTP *smtp = data->state.proto.smtp;
|
|
||||||
|
|
||||||
/* Send the RCPT TO command */
|
|
||||||
if(smtp->rcpt) {
|
|
||||||
if(smtp->rcpt->data[0] == '<')
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
|
|
||||||
smtp->rcpt->data);
|
|
||||||
else
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
|
|
||||||
smtp->rcpt->data);
|
|
||||||
if(!result)
|
|
||||||
state(conn, SMTP_RCPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For MAIL responses */
|
/* For MAIL responses */
|
||||||
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
||||||
smtpstate instate)
|
smtpstate instate)
|
||||||
@@ -1037,7 +1127,7 @@ static CURLcode smtp_state_mail_resp(struct connectdata *conn, int smtpcode,
|
|||||||
else {
|
else {
|
||||||
smtp->rcpt = data->set.mail_rcpt;
|
smtp->rcpt = data->set.mail_rcpt;
|
||||||
|
|
||||||
result = smtp_rcpt_to(conn);
|
result = smtp_perform_rcpt_to(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -1061,7 +1151,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
|||||||
else {
|
else {
|
||||||
if(smtp->rcpt) {
|
if(smtp->rcpt) {
|
||||||
smtp->rcpt = smtp->rcpt->next;
|
smtp->rcpt = smtp->rcpt->next;
|
||||||
result = smtp_rcpt_to(conn);
|
result = smtp_perform_rcpt_to(conn);
|
||||||
|
|
||||||
/* If we failed or still are sending RCPT data then return */
|
/* If we failed or still are sending RCPT data then return */
|
||||||
if(result || smtp->rcpt)
|
if(result || smtp->rcpt)
|
||||||
@@ -1082,6 +1172,8 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn, int smtpcode,
|
|||||||
static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
|
static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
|
||||||
smtpstate instate)
|
smtpstate instate)
|
||||||
{
|
{
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
(void)instate; /* no use for this yet */
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
if(smtpcode != 354) {
|
if(smtpcode != 354) {
|
||||||
@@ -1089,6 +1181,9 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode,
|
|||||||
return CURLE_SEND_ERROR;
|
return CURLE_SEND_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the progress upload size */
|
||||||
|
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||||
|
|
||||||
/* SMTP upload */
|
/* SMTP upload */
|
||||||
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
|
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
|
||||||
|
|
||||||
@@ -1129,7 +1224,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
|
|||||||
|
|
||||||
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
|
/* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */
|
||||||
if(smtpc->state == SMTP_UPGRADETLS)
|
if(smtpc->state == SMTP_UPGRADETLS)
|
||||||
return smtp_state_upgrade_tls(conn);
|
return smtp_perform_upgrade_tls(conn);
|
||||||
|
|
||||||
/* Flush any data that needs to be sent */
|
/* Flush any data that needs to be sent */
|
||||||
if(pp->sendleft)
|
if(pp->sendleft)
|
||||||
@@ -1300,8 +1395,6 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
|||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
struct pingpong *pp = &smtpc->pp;
|
struct pingpong *pp = &smtpc->pp;
|
||||||
const char *path = conn->data->state.path;
|
|
||||||
char localhost[HOSTNAME_MAX + 1];
|
|
||||||
|
|
||||||
*done = FALSE; /* default to not done yet */
|
*done = FALSE; /* default to not done yet */
|
||||||
|
|
||||||
@@ -1323,19 +1416,19 @@ static CURLcode smtp_connect(struct connectdata *conn, bool *done)
|
|||||||
pp->endofresp = smtp_endofresp;
|
pp->endofresp = smtp_endofresp;
|
||||||
pp->conn = conn;
|
pp->conn = conn;
|
||||||
|
|
||||||
|
/* Set the default preferred authentication mechanism */
|
||||||
|
smtpc->prefmech = SASL_AUTH_ANY;
|
||||||
|
|
||||||
/* Initialise the pingpong layer */
|
/* Initialise the pingpong layer */
|
||||||
Curl_pp_init(pp);
|
Curl_pp_init(pp);
|
||||||
|
|
||||||
/* Calculate the path if necessary */
|
/* Parse the URL options */
|
||||||
if(!*path) {
|
result = smtp_parse_url_options(conn);
|
||||||
if(!Curl_gethostname(localhost, sizeof(localhost)))
|
if(result)
|
||||||
path = localhost;
|
return result;
|
||||||
else
|
|
||||||
path = "localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* URL decode the path and use it as the domain in our EHLO */
|
/* Parse the URL path */
|
||||||
result = Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
|
result = smtp_parse_url_path(conn);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1362,6 +1455,9 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
|||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct SMTP *smtp = data->state.proto.smtp;
|
struct SMTP *smtp = data->state.proto.smtp;
|
||||||
|
struct pingpong *pp = &conn->proto.smtpc.pp;
|
||||||
|
const char *eob;
|
||||||
|
ssize_t len;
|
||||||
ssize_t bytes_written;
|
ssize_t bytes_written;
|
||||||
|
|
||||||
(void)premature;
|
(void)premature;
|
||||||
@@ -1378,25 +1474,27 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status,
|
|||||||
result = status; /* use the already set error code */
|
result = status; /* use the already set error code */
|
||||||
}
|
}
|
||||||
else if(!data->set.connect_only) {
|
else if(!data->set.connect_only) {
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
/* Calculate the EOB taking into account any terminating CRLF from the
|
||||||
struct pingpong *pp = &smtpc->pp;
|
previous line of the email or the CRLF of the DATA command when there
|
||||||
|
is "no mail data". RFC-5321, sect. 4.1.1.4. */
|
||||||
|
eob = SMTP_EOB;
|
||||||
|
len = SMTP_EOB_LEN;
|
||||||
|
if(smtp->trailing_crlf || !conn->data->set.infilesize) {
|
||||||
|
eob += 2;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the end of block data */
|
/* Send the end of block data */
|
||||||
result = Curl_write(conn,
|
result = Curl_write(conn, conn->writesockfd, eob, len, &bytes_written);
|
||||||
conn->writesockfd, /* socket to send to */
|
|
||||||
SMTP_EOB, /* buffer pointer */
|
|
||||||
SMTP_EOB_LEN, /* buffer size */
|
|
||||||
&bytes_written); /* actually sent away */
|
|
||||||
|
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if(bytes_written != SMTP_EOB_LEN) {
|
if(bytes_written != len) {
|
||||||
/* The whole chunk was not sent so keep it around and adjust the
|
/* The whole chunk was not sent so keep it around and adjust the
|
||||||
pingpong structure accordingly */
|
pingpong structure accordingly */
|
||||||
pp->sendthis = strdup(SMTP_EOB);
|
pp->sendthis = strdup(eob);
|
||||||
pp->sendsize = SMTP_EOB_LEN;
|
pp->sendsize = len;
|
||||||
pp->sendleft = SMTP_EOB_LEN - bytes_written;
|
pp->sendleft = len - bytes_written;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Successfully sent so adjust the response timeout relative to now */
|
/* Successfully sent so adjust the response timeout relative to now */
|
||||||
@@ -1444,7 +1542,7 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
|
|||||||
*dophase_done = FALSE; /* not done yet */
|
*dophase_done = FALSE; /* not done yet */
|
||||||
|
|
||||||
/* Start the first command in the DO phase */
|
/* Start the first command in the DO phase */
|
||||||
result = smtp_mail(conn);
|
result = smtp_perform_mail(conn);
|
||||||
if(result)
|
if(result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -1488,25 +1586,6 @@ static CURLcode smtp_do(struct connectdata *conn, bool *done)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
*
|
|
||||||
* smtp_quit()
|
|
||||||
*
|
|
||||||
* Performs the quit action prior to sclose() being called.
|
|
||||||
*/
|
|
||||||
static CURLcode smtp_quit(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
|
|
||||||
/* Send the QUIT command */
|
|
||||||
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
|
|
||||||
|
|
||||||
if(!result)
|
|
||||||
state(conn, SMTP_QUIT);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
*
|
*
|
||||||
* smtp_disconnect()
|
* smtp_disconnect()
|
||||||
@@ -1526,7 +1605,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn,
|
|||||||
/* The SMTP session may or may not have been allocated/setup at this
|
/* The SMTP session may or may not have been allocated/setup at this
|
||||||
point! */
|
point! */
|
||||||
if(!dead_connection && smtpc->pp.conn)
|
if(!dead_connection && smtpc->pp.conn)
|
||||||
if(!smtp_quit(conn))
|
if(!smtp_perform_quit(conn))
|
||||||
(void)smtp_block_statemach(conn); /* ignore errors on QUIT */
|
(void)smtp_block_statemach(conn); /* ignore errors on QUIT */
|
||||||
|
|
||||||
/* Disconnect from the server */
|
/* Disconnect from the server */
|
||||||
@@ -1640,18 +1719,90 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_parse_url_options()
|
||||||
|
*
|
||||||
|
* Parse the URL login options.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_parse_url_options(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
|
const char *options = conn->options;
|
||||||
|
const char *ptr = options;
|
||||||
|
|
||||||
|
if(options) {
|
||||||
|
const char *key = ptr;
|
||||||
|
|
||||||
|
while(*ptr && *ptr != '=')
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
if(strnequal(key, "AUTH", 4)) {
|
||||||
|
const char *value = ptr + 1;
|
||||||
|
|
||||||
|
if(strequal(value, "*"))
|
||||||
|
smtpc->prefmech = SASL_AUTH_ANY;
|
||||||
|
else if(strequal(value, "LOGIN"))
|
||||||
|
smtpc->prefmech = SASL_MECH_LOGIN;
|
||||||
|
else if(strequal(value, "PLAIN"))
|
||||||
|
smtpc->prefmech = SASL_MECH_PLAIN;
|
||||||
|
else if(strequal(value, "CRAM-MD5"))
|
||||||
|
smtpc->prefmech = SASL_MECH_CRAM_MD5;
|
||||||
|
else if(strequal(value, "DIGEST-MD5"))
|
||||||
|
smtpc->prefmech = SASL_MECH_DIGEST_MD5;
|
||||||
|
else if(strequal(value, "GSSAPI"))
|
||||||
|
smtpc->prefmech = SASL_MECH_GSSAPI;
|
||||||
|
else if(strequal(value, "NTLM"))
|
||||||
|
smtpc->prefmech = SASL_MECH_NTLM;
|
||||||
|
else
|
||||||
|
smtpc->prefmech = SASL_AUTH_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = CURLE_URL_MALFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* smtp_parse_url_path()
|
||||||
|
*
|
||||||
|
* Parse the URL path into separate path components.
|
||||||
|
*/
|
||||||
|
static CURLcode smtp_parse_url_path(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
/* The SMTP struct is already initialised in smtp_connect() */
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
|
const char *path = data->state.path;
|
||||||
|
char localhost[HOSTNAME_MAX + 1];
|
||||||
|
|
||||||
|
/* Calculate the path if necessary */
|
||||||
|
if(!*path) {
|
||||||
|
if(!Curl_gethostname(localhost, sizeof(localhost)))
|
||||||
|
path = localhost;
|
||||||
|
else
|
||||||
|
path = "localhost";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* URL decode the path and use it as the domain in our EHLO */
|
||||||
|
return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
|
CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
|
||||||
{
|
{
|
||||||
/* When sending a SMTP payload we must detect CRLF. sequences making sure
|
/* When sending a SMTP payload we must detect CRLF. sequences making sure
|
||||||
they are sent as CRLF.. instead, as a . on the beginning of a line will
|
they are sent as CRLF.. instead, as a . on the beginning of a line will
|
||||||
be deleted by the server when not part of an EOB terminator and a
|
be deleted by the server when not part of an EOB terminator and a
|
||||||
genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of
|
genuine CRLF.CRLF which isn't escaped will wrongly be detected as end of
|
||||||
data by the server.
|
data by the server
|
||||||
*/
|
*/
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
ssize_t si;
|
ssize_t si;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct SMTP *smtp = data->state.proto.smtp;
|
||||||
|
|
||||||
/* Do we need to allocate the scatch buffer? */
|
/* Do we need to allocate the scatch buffer? */
|
||||||
if(!data->state.scratch) {
|
if(!data->state.scratch) {
|
||||||
@@ -1666,36 +1817,46 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
|
|||||||
/* This loop can be improved by some kind of Boyer-Moore style of
|
/* This loop can be improved by some kind of Boyer-Moore style of
|
||||||
approach but that is saved for later... */
|
approach but that is saved for later... */
|
||||||
for(i = 0, si = 0; i < nread; i++) {
|
for(i = 0, si = 0; i < nread; i++) {
|
||||||
if(SMTP_EOB[smtpc->eob] == data->req.upload_fromhere[i])
|
if(SMTP_EOB[smtp->eob] == data->req.upload_fromhere[i]) {
|
||||||
smtpc->eob++;
|
smtp->eob++;
|
||||||
else if(smtpc->eob) {
|
|
||||||
|
/* Is the EOB potentially the terminating CRLF? */
|
||||||
|
if(2 == smtp->eob || SMTP_EOB_LEN == smtp->eob)
|
||||||
|
smtp->trailing_crlf = TRUE;
|
||||||
|
else
|
||||||
|
smtp->trailing_crlf = FALSE;
|
||||||
|
}
|
||||||
|
else if(smtp->eob) {
|
||||||
/* A previous substring matched so output that first */
|
/* A previous substring matched so output that first */
|
||||||
memcpy(&data->state.scratch[si], SMTP_EOB, smtpc->eob);
|
memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
|
||||||
si += smtpc->eob;
|
si += smtp->eob;
|
||||||
|
|
||||||
/* Then compare the first byte */
|
/* Then compare the first byte */
|
||||||
if(SMTP_EOB[0] == data->req.upload_fromhere[i])
|
if(SMTP_EOB[0] == data->req.upload_fromhere[i])
|
||||||
smtpc->eob = 1;
|
smtp->eob = 1;
|
||||||
else
|
else
|
||||||
smtpc->eob = 0;
|
smtp->eob = 0;
|
||||||
|
|
||||||
|
/* Reset the trailing CRLF flag as there was more data */
|
||||||
|
smtp->trailing_crlf = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do we have a match for CRLF. as per RFC-2821, sect. 4.5.2 */
|
/* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */
|
||||||
if(SMTP_EOB_FIND_LEN == smtpc->eob) {
|
if(SMTP_EOB_FIND_LEN == smtp->eob) {
|
||||||
/* Copy the replacement data to the target buffer */
|
/* Copy the replacement data to the target buffer */
|
||||||
memcpy(&data->state.scratch[si], SMTP_EOB_REPL, SMTP_EOB_REPL_LEN);
|
memcpy(&data->state.scratch[si], SMTP_EOB_REPL, SMTP_EOB_REPL_LEN);
|
||||||
si += SMTP_EOB_REPL_LEN;
|
si += SMTP_EOB_REPL_LEN;
|
||||||
smtpc->eob = 0;
|
smtp->eob = 0;
|
||||||
}
|
}
|
||||||
else if(!smtpc->eob)
|
else if(!smtp->eob)
|
||||||
data->state.scratch[si++] = data->req.upload_fromhere[i];
|
data->state.scratch[si++] = data->req.upload_fromhere[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(smtpc->eob) {
|
if(smtp->eob) {
|
||||||
/* A substring matched before processing ended so output that now */
|
/* A substring matched before processing ended so output that now */
|
||||||
memcpy(&data->state.scratch[si], SMTP_EOB, smtpc->eob);
|
memcpy(&data->state.scratch[si], SMTP_EOB, smtp->eob);
|
||||||
si += smtpc->eob;
|
si += smtp->eob;
|
||||||
smtpc->eob = 0;
|
smtp->eob = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(si != nread) {
|
if(si != nread) {
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ typedef enum {
|
|||||||
struct SMTP {
|
struct SMTP {
|
||||||
curl_pp_transfer transfer;
|
curl_pp_transfer transfer;
|
||||||
struct curl_slist *rcpt; /* Recipient list */
|
struct curl_slist *rcpt; /* Recipient list */
|
||||||
|
size_t eob; /* Number of bytes of the EOB (End Of Body) that
|
||||||
|
have been received so far */
|
||||||
|
bool trailing_crlf; /* Specifies if the tailing CRLF is present */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* smtp_conn is used for struct connection-oriented data in the connectdata
|
/* smtp_conn is used for struct connection-oriented data in the connectdata
|
||||||
@@ -69,9 +72,8 @@ struct smtp_conn {
|
|||||||
smtpstate state; /* Always use smtp.c:state() to change state! */
|
smtpstate state; /* Always use smtp.c:state() to change state! */
|
||||||
bool ssldone; /* Is connect() over SSL done? */
|
bool ssldone; /* Is connect() over SSL done? */
|
||||||
char *domain; /* Client address/name to send in the EHLO */
|
char *domain; /* Client address/name to send in the EHLO */
|
||||||
size_t eob; /* Number of bytes of the EOB (End Of Body) that
|
|
||||||
have been received so far */
|
|
||||||
unsigned int authmechs; /* Accepted authentication mechanisms */
|
unsigned int authmechs; /* Accepted authentication mechanisms */
|
||||||
|
unsigned int prefmech; /* Preferred authentication mechanism */
|
||||||
unsigned int authused; /* Auth mechanism used for the connection */
|
unsigned int authused; /* Auth mechanism used for the connection */
|
||||||
bool tls_supported; /* StartTLS capability supported by server */
|
bool tls_supported; /* StartTLS capability supported by server */
|
||||||
bool size_supported; /* If server supports SIZE extension according to
|
bool size_supported; /* If server supports SIZE extension according to
|
||||||
|
|||||||
60
lib/ssluse.c
60
lib/ssluse.c
@@ -447,54 +447,53 @@ int cert_stuff(struct connectdata *conn,
|
|||||||
|
|
||||||
if(SSL_CTX_use_certificate(ctx, x509) != 1) {
|
if(SSL_CTX_use_certificate(ctx, x509) != 1) {
|
||||||
failf(data, SSL_CLIENT_CERT_ERR);
|
failf(data, SSL_CLIENT_CERT_ERR);
|
||||||
EVP_PKEY_free(pri);
|
goto fail;
|
||||||
X509_free(x509);
|
|
||||||
sk_X509_pop_free(ca, X509_free);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
|
if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
|
||||||
failf(data, "unable to use private key from PKCS12 file '%s'",
|
failf(data, "unable to use private key from PKCS12 file '%s'",
|
||||||
cert_file);
|
cert_file);
|
||||||
EVP_PKEY_free(pri);
|
goto fail;
|
||||||
X509_free(x509);
|
|
||||||
sk_X509_pop_free(ca, X509_free);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!SSL_CTX_check_private_key (ctx)) {
|
if(!SSL_CTX_check_private_key (ctx)) {
|
||||||
failf(data, "private key from PKCS12 file '%s' "
|
failf(data, "private key from PKCS12 file '%s' "
|
||||||
"does not match certificate in same file", cert_file);
|
"does not match certificate in same file", cert_file);
|
||||||
EVP_PKEY_free(pri);
|
goto fail;
|
||||||
X509_free(x509);
|
|
||||||
sk_X509_pop_free(ca, X509_free);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
/* Set Certificate Verification chain */
|
/* Set Certificate Verification chain */
|
||||||
if(ca && sk_X509_num(ca)) {
|
if(ca && sk_X509_num(ca)) {
|
||||||
for(i = 0; i < sk_X509_num(ca); i++) {
|
for(i = 0; i < sk_X509_num(ca); i++) {
|
||||||
if(!SSL_CTX_add_extra_chain_cert(ctx,sk_X509_value(ca, i))) {
|
/*
|
||||||
|
* Note that sk_X509_pop() is used below to make sure the cert is
|
||||||
|
* removed from the stack properly before getting passed to
|
||||||
|
* SSL_CTX_add_extra_chain_cert(). Previously we used
|
||||||
|
* sk_X509_value() instead, but then we'd clean it in the subsequent
|
||||||
|
* sk_X509_pop_free() call.
|
||||||
|
*/
|
||||||
|
X509 *x = sk_X509_pop(ca);
|
||||||
|
if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
|
||||||
failf(data, "cannot add certificate to certificate chain");
|
failf(data, "cannot add certificate to certificate chain");
|
||||||
EVP_PKEY_free(pri);
|
goto fail;
|
||||||
X509_free(x509);
|
|
||||||
sk_X509_pop_free(ca, X509_free);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if(!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) {
|
/* SSL_CTX_add_client_CA() seems to work with either sk_* function,
|
||||||
|
* presumably because it duplicates what we pass to it.
|
||||||
|
*/
|
||||||
|
if(!SSL_CTX_add_client_CA(ctx, x)) {
|
||||||
failf(data, "cannot add certificate to client CA list");
|
failf(data, "cannot add certificate to client CA list");
|
||||||
EVP_PKEY_free(pri);
|
goto fail;
|
||||||
X509_free(x509);
|
|
||||||
sk_X509_pop_free(ca, X509_free);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cert_done = 1;
|
||||||
|
fail:
|
||||||
EVP_PKEY_free(pri);
|
EVP_PKEY_free(pri);
|
||||||
X509_free(x509);
|
X509_free(x509);
|
||||||
sk_X509_pop_free(ca, X509_free);
|
sk_X509_pop_free(ca, X509_free);
|
||||||
cert_done = 1;
|
|
||||||
break;
|
if(!cert_done)
|
||||||
|
return 0; /* failure! */
|
||||||
#else
|
#else
|
||||||
failf(data, "file type P12 for certificate not supported");
|
failf(data, "file type P12 for certificate not supported");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2205,14 +2204,7 @@ static CURLcode servercert(struct connectdata *conn,
|
|||||||
|
|
||||||
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
|
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
|
||||||
buffer, BUFSIZE);
|
buffer, BUFSIZE);
|
||||||
if(rc) {
|
infof(data, "\t subject: %s\n", rc?"[NONE]":buffer);
|
||||||
if(strict)
|
|
||||||
failf(data, "SSL: couldn't get X509-subject!");
|
|
||||||
X509_free(connssl->server_cert);
|
|
||||||
connssl->server_cert = NULL;
|
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
|
||||||
}
|
|
||||||
infof(data, "\t subject: %s\n", buffer);
|
|
||||||
|
|
||||||
certdate = X509_get_notBefore(connssl->server_cert);
|
certdate = X509_get_notBefore(connssl->server_cert);
|
||||||
asn1_output(certdate, buffer, BUFSIZE);
|
asn1_output(certdate, buffer, BUFSIZE);
|
||||||
@@ -2553,7 +2545,7 @@ static ssize_t ossl_send(struct connectdata *conn,
|
|||||||
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
|
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
|
||||||
rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
|
rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
|
||||||
|
|
||||||
if(rc < 0) {
|
if(rc <= 0) {
|
||||||
err = SSL_get_error(conn->ssl[sockindex].handle, rc);
|
err = SSL_get_error(conn->ssl[sockindex].handle, rc);
|
||||||
|
|
||||||
switch(err) {
|
switch(err) {
|
||||||
@@ -2602,7 +2594,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
|
|||||||
|
|
||||||
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
|
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
|
||||||
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
|
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
|
||||||
if(nread < 0) {
|
if(nread <= 0) {
|
||||||
/* failed SSL_read */
|
/* failed SSL_read */
|
||||||
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
|
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
|
||||||
|
|
||||||
|
|||||||
427
lib/url.c
427
lib/url.c
@@ -141,9 +141,12 @@ find_oldest_idle_connection_in_bundle(struct SessionHandle *data,
|
|||||||
static void conn_free(struct connectdata *conn);
|
static void conn_free(struct connectdata *conn);
|
||||||
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
|
static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
|
||||||
static CURLcode do_init(struct connectdata *conn);
|
static CURLcode do_init(struct connectdata *conn);
|
||||||
static CURLcode parse_url_userpass(struct SessionHandle *data,
|
static CURLcode parse_url_login(struct SessionHandle *data,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn,
|
||||||
char *user, char *passwd);
|
char *user, char *passwd, char *options);
|
||||||
|
static CURLcode parse_login_details(const char *login, const size_t len,
|
||||||
|
char **userptr, char **passwdptr,
|
||||||
|
char **optionsptr);
|
||||||
/*
|
/*
|
||||||
* Protocol table.
|
* Protocol table.
|
||||||
*/
|
*/
|
||||||
@@ -261,7 +264,7 @@ static const struct Curl_handler Curl_handler_dummy = {
|
|||||||
PROTOPT_NONE /* flags */
|
PROTOPT_NONE /* flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
void Curl_freeset(struct SessionHandle * data)
|
void Curl_freeset(struct SessionHandle *data)
|
||||||
{
|
{
|
||||||
/* Free all dynamic strings stored in the data->set substructure. */
|
/* Free all dynamic strings stored in the data->set substructure. */
|
||||||
enum dupstring i;
|
enum dupstring i;
|
||||||
@@ -275,7 +278,7 @@ void Curl_freeset(struct SessionHandle * data)
|
|||||||
data->change.referer = NULL;
|
data->change.referer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode setstropt(char **charp, char * s)
|
static CURLcode setstropt(char **charp, char *s)
|
||||||
{
|
{
|
||||||
/* Release the previous storage at `charp' and replace by a dynamic storage
|
/* Release the previous storage at `charp' and replace by a dynamic storage
|
||||||
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
|
copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
|
||||||
@@ -294,48 +297,47 @@ static CURLcode setstropt(char **charp, char * s)
|
|||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode setstropt_userpwd(char *option, char **user_storage,
|
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp,
|
||||||
char **pwd_storage)
|
char **optionsp)
|
||||||
{
|
{
|
||||||
char* separator;
|
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
char *user = NULL;
|
||||||
|
char *passwd = NULL;
|
||||||
|
char *options = NULL;
|
||||||
|
|
||||||
if(!option) {
|
/* Parse the login details if specified. It not then we treat NULL as a hint
|
||||||
/* we treat a NULL passed in as a hint to clear existing info */
|
to clear the existing data */
|
||||||
Curl_safefree(*user_storage);
|
if(option) {
|
||||||
*user_storage = (char *) NULL;
|
result = parse_login_details(option, strlen(option),
|
||||||
Curl_safefree(*pwd_storage);
|
(userp ? &user : NULL),
|
||||||
*pwd_storage = (char *) NULL;
|
(passwdp ? &passwd : NULL),
|
||||||
return CURLE_OK;
|
(optionsp ? &options : NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
separator = strchr(option, ':');
|
if(!result) {
|
||||||
if(separator != NULL) {
|
/* Store the username part of option if required */
|
||||||
|
if(userp) {
|
||||||
/* store username part of option */
|
Curl_safefree(*userp);
|
||||||
char * p;
|
*userp = user;
|
||||||
size_t username_len = (size_t)(separator-option);
|
|
||||||
p = malloc(username_len+1);
|
|
||||||
if(!p)
|
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
|
||||||
else {
|
|
||||||
memcpy(p, option, username_len);
|
|
||||||
p[username_len] = '\0';
|
|
||||||
Curl_safefree(*user_storage);
|
|
||||||
*user_storage = p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store password part of option */
|
/* Store the password part of option if required */
|
||||||
if(result == CURLE_OK)
|
if(passwdp) {
|
||||||
result = setstropt(pwd_storage, separator+1);
|
Curl_safefree(*passwdp);
|
||||||
|
*passwdp = passwd;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
result = setstropt(user_storage, option);
|
/* Store the options part of option if required */
|
||||||
|
if(optionsp) {
|
||||||
|
Curl_safefree(*optionsp);
|
||||||
|
*optionsp = options;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src)
|
CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
|
||||||
{
|
{
|
||||||
CURLcode r = CURLE_OK;
|
CURLcode r = CURLE_OK;
|
||||||
enum dupstring i;
|
enum dupstring i;
|
||||||
@@ -1135,22 +1137,21 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
if(argptr == NULL)
|
if(argptr == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||||
|
|
||||||
if(Curl_raw_equal(argptr, "ALL")) {
|
if(Curl_raw_equal(argptr, "ALL")) {
|
||||||
/* clear all cookies */
|
/* clear all cookies */
|
||||||
Curl_cookie_clearall(data->cookies);
|
Curl_cookie_clearall(data->cookies);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if(Curl_raw_equal(argptr, "SESS")) {
|
else if(Curl_raw_equal(argptr, "SESS")) {
|
||||||
/* clear session cookies */
|
/* clear session cookies */
|
||||||
Curl_cookie_clearsess(data->cookies);
|
Curl_cookie_clearsess(data->cookies);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if(Curl_raw_equal(argptr, "FLUSH")) {
|
else if(Curl_raw_equal(argptr, "FLUSH")) {
|
||||||
/* flush cookies to file */
|
/* flush cookies to file */
|
||||||
Curl_flush_cookies(data, 0);
|
Curl_flush_cookies(data, 0);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if(!data->cookies)
|
if(!data->cookies)
|
||||||
/* if cookie engine was not running, activate it */
|
/* if cookie engine was not running, activate it */
|
||||||
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
|
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
|
||||||
@@ -1158,8 +1159,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
argptr = strdup(argptr);
|
argptr = strdup(argptr);
|
||||||
if(!argptr) {
|
if(!argptr) {
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
if(checkprefix("Set-Cookie:", argptr))
|
if(checkprefix("Set-Cookie:", argptr))
|
||||||
/* HTTP Header format line */
|
/* HTTP Header format line */
|
||||||
@@ -1170,6 +1171,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
|
Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
|
||||||
|
|
||||||
free(argptr);
|
free(argptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* CURL_DISABLE_COOKIES */
|
#endif /* CURL_DISABLE_COOKIES */
|
||||||
|
|
||||||
@@ -1534,11 +1539,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
|
|
||||||
case CURLOPT_USERPWD:
|
case CURLOPT_USERPWD:
|
||||||
/*
|
/*
|
||||||
* user:password to use in the operation
|
* user:password;options to use in the operation
|
||||||
*/
|
*/
|
||||||
result = setstropt_userpwd(va_arg(param, char *),
|
result = setstropt_userpwd(va_arg(param, char *),
|
||||||
&data->set.str[STRING_USERNAME],
|
&data->set.str[STRING_USERNAME],
|
||||||
&data->set.str[STRING_PASSWORD]);
|
&data->set.str[STRING_PASSWORD],
|
||||||
|
&data->set.str[STRING_OPTIONS]);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_USERNAME:
|
case CURLOPT_USERNAME:
|
||||||
/*
|
/*
|
||||||
@@ -1611,7 +1617,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
*/
|
*/
|
||||||
result = setstropt_userpwd(va_arg(param, char *),
|
result = setstropt_userpwd(va_arg(param, char *),
|
||||||
&data->set.str[STRING_PROXYUSERNAME],
|
&data->set.str[STRING_PROXYUSERNAME],
|
||||||
&data->set.str[STRING_PROXYPASSWORD]);
|
&data->set.str[STRING_PROXYPASSWORD], NULL);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_PROXYUSERNAME:
|
case CURLOPT_PROXYUSERNAME:
|
||||||
/*
|
/*
|
||||||
@@ -2243,20 +2249,27 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CURLOPT_MAIL_FROM:
|
case CURLOPT_MAIL_FROM:
|
||||||
|
/* Set the SMTP mail originator */
|
||||||
result = setstropt(&data->set.str[STRING_MAIL_FROM],
|
result = setstropt(&data->set.str[STRING_MAIL_FROM],
|
||||||
va_arg(param, char *));
|
va_arg(param, char *));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CURLOPT_MAIL_AUTH:
|
case CURLOPT_MAIL_AUTH:
|
||||||
|
/* Set the SMTP auth originator */
|
||||||
result = setstropt(&data->set.str[STRING_MAIL_AUTH],
|
result = setstropt(&data->set.str[STRING_MAIL_AUTH],
|
||||||
va_arg(param, char *));
|
va_arg(param, char *));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CURLOPT_MAIL_RCPT:
|
case CURLOPT_MAIL_RCPT:
|
||||||
/* get a list of mail recipients */
|
/* Set the list of mail recipients */
|
||||||
data->set.mail_rcpt = va_arg(param, struct curl_slist *);
|
data->set.mail_rcpt = va_arg(param, struct curl_slist *);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CURLOPT_SASL_IR:
|
||||||
|
/* Enable/disable SASL initial response */
|
||||||
|
data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
case CURLOPT_RTSP_REQUEST:
|
case CURLOPT_RTSP_REQUEST:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -2452,6 +2465,7 @@ static void conn_free(struct connectdata *conn)
|
|||||||
|
|
||||||
Curl_safefree(conn->user);
|
Curl_safefree(conn->user);
|
||||||
Curl_safefree(conn->passwd);
|
Curl_safefree(conn->passwd);
|
||||||
|
Curl_safefree(conn->options);
|
||||||
Curl_safefree(conn->proxyuser);
|
Curl_safefree(conn->proxyuser);
|
||||||
Curl_safefree(conn->proxypasswd);
|
Curl_safefree(conn->proxypasswd);
|
||||||
Curl_safefree(conn->allocptr.proxyuserpwd);
|
Curl_safefree(conn->allocptr.proxyuserpwd);
|
||||||
@@ -3650,8 +3664,7 @@ static CURLcode findprotocol(struct SessionHandle *data,
|
|||||||
static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn,
|
||||||
bool *prot_missing,
|
bool *prot_missing,
|
||||||
char *user,
|
char *user, char *passwd, char *options)
|
||||||
char *passwd)
|
|
||||||
{
|
{
|
||||||
char *at;
|
char *at;
|
||||||
char *fragment;
|
char *fragment;
|
||||||
@@ -3768,6 +3781,10 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
|||||||
protop = "LDAP";
|
protop = "LDAP";
|
||||||
else if(checkprefix("IMAP.", conn->host.name))
|
else if(checkprefix("IMAP.", conn->host.name))
|
||||||
protop = "IMAP";
|
protop = "IMAP";
|
||||||
|
else if(checkprefix("SMTP.", conn->host.name))
|
||||||
|
protop = "smtp";
|
||||||
|
else if(checkprefix("POP3.", conn->host.name))
|
||||||
|
protop = "pop3";
|
||||||
else {
|
else {
|
||||||
protop = "http";
|
protop = "http";
|
||||||
}
|
}
|
||||||
@@ -3865,11 +3882,11 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
|
|||||||
data->change.url_alloc = TRUE; /* free this later */
|
data->change.url_alloc = TRUE; /* free this later */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*
|
||||||
* Parse a user name and password in the URL and strip it out
|
* Parse the login details from the URL and strip them out of
|
||||||
* of the host name
|
* the host name
|
||||||
*************************************************************/
|
*/
|
||||||
result = parse_url_userpass(data, conn, user, passwd);
|
result = parse_url_login(data, conn, user, passwd, options);
|
||||||
if(result != CURLE_OK)
|
if(result != CURLE_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -4193,34 +4210,37 @@ static CURLcode parse_proxy(struct SessionHandle *data,
|
|||||||
/* Is there a username and password given in this proxy url? */
|
/* Is there a username and password given in this proxy url? */
|
||||||
atsign = strchr(proxyptr, '@');
|
atsign = strchr(proxyptr, '@');
|
||||||
if(atsign) {
|
if(atsign) {
|
||||||
char proxyuser[MAX_CURL_USER_LENGTH];
|
|
||||||
char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
|
|
||||||
proxypasswd[0] = 0;
|
|
||||||
|
|
||||||
if(1 <= sscanf(proxyptr,
|
|
||||||
"%" MAX_CURL_USER_LENGTH_TXT"[^:@]:"
|
|
||||||
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
|
|
||||||
proxyuser, proxypasswd)) {
|
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
|
char *proxyuser = NULL;
|
||||||
|
char *proxypasswd = NULL;
|
||||||
|
|
||||||
|
res = parse_login_details(proxyptr, atsign - proxyptr,
|
||||||
|
&proxyuser, &proxypasswd, NULL);
|
||||||
|
if(!res) {
|
||||||
/* found user and password, rip them out. note that we are
|
/* found user and password, rip them out. note that we are
|
||||||
unescaping them, as there is otherwise no way to have a
|
unescaping them, as there is otherwise no way to have a
|
||||||
username or password with reserved characters like ':' in
|
username or password with reserved characters like ':' in
|
||||||
them. */
|
them. */
|
||||||
Curl_safefree(conn->proxyuser);
|
Curl_safefree(conn->proxyuser);
|
||||||
|
if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
|
||||||
conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
|
conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
|
||||||
|
else
|
||||||
|
conn->proxyuser = strdup("");
|
||||||
|
|
||||||
if(!conn->proxyuser)
|
if(!conn->proxyuser)
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
res = CURLE_OUT_OF_MEMORY;
|
||||||
else {
|
else {
|
||||||
Curl_safefree(conn->proxypasswd);
|
Curl_safefree(conn->proxypasswd);
|
||||||
|
if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
|
||||||
conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
|
conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
|
||||||
|
else
|
||||||
|
conn->proxypasswd = strdup("");
|
||||||
|
|
||||||
if(!conn->proxypasswd)
|
if(!conn->proxypasswd)
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
res = CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CURLE_OK == res) {
|
if(!res) {
|
||||||
conn->bits.proxy_user_passwd = TRUE; /* enable it */
|
conn->bits.proxy_user_passwd = TRUE; /* enable it */
|
||||||
atsign++; /* the right side of the @-letter */
|
atsign++; /* the right side of the @-letter */
|
||||||
|
|
||||||
@@ -4229,11 +4249,14 @@ static CURLcode parse_proxy(struct SessionHandle *data,
|
|||||||
else
|
else
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
res = CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_safefree(proxyuser);
|
||||||
|
Curl_safefree(proxypasswd);
|
||||||
|
|
||||||
if(res)
|
if(res)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* start scanning for port number at this point */
|
/* start scanning for port number at this point */
|
||||||
portptr = proxyptr;
|
portptr = proxyptr;
|
||||||
@@ -4326,8 +4349,10 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
|
|||||||
#endif /* CURL_DISABLE_PROXY */
|
#endif /* CURL_DISABLE_PROXY */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* parse_url_login()
|
||||||
*
|
*
|
||||||
* Parse a user name and password in the URL and strip it out of the host name
|
* Parse the login details (user name, password and options) from the URL and
|
||||||
|
* strip them out of the host name
|
||||||
*
|
*
|
||||||
* Inputs: data->set.use_netrc (CURLOPT_NETRC)
|
* Inputs: data->set.use_netrc (CURLOPT_NETRC)
|
||||||
* conn->host.name
|
* conn->host.name
|
||||||
@@ -4335,31 +4360,38 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
|
|||||||
* Outputs: (almost :- all currently undefined)
|
* Outputs: (almost :- all currently undefined)
|
||||||
* conn->bits.user_passwd - non-zero if non-default passwords exist
|
* conn->bits.user_passwd - non-zero if non-default passwords exist
|
||||||
* user - non-zero length if defined
|
* user - non-zero length if defined
|
||||||
* passwd - ditto
|
* passwd - non-zero length if defined
|
||||||
|
* options - non-zero length if defined
|
||||||
* conn->host.name - remove user name and password
|
* conn->host.name - remove user name and password
|
||||||
*/
|
*/
|
||||||
static CURLcode parse_url_userpass(struct SessionHandle *data,
|
static CURLcode parse_url_login(struct SessionHandle *data,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn,
|
||||||
char *user, char *passwd)
|
char *user, char *passwd, char *options)
|
||||||
{
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
char *userp = NULL;
|
||||||
|
char *passwdp = NULL;
|
||||||
|
char *optionsp = NULL;
|
||||||
|
|
||||||
/* At this point, we're hoping all the other special cases have
|
/* At this point, we're hoping all the other special cases have
|
||||||
* been taken care of, so conn->host.name is at most
|
* been taken care of, so conn->host.name is at most
|
||||||
* [user[:password]]@]hostname
|
* [user[:password][;options]]@]hostname
|
||||||
*
|
*
|
||||||
* We need somewhere to put the embedded details, so do that first.
|
* We need somewhere to put the embedded details, so do that first.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *ptr=strchr(conn->host.name, '@');
|
char *ptr = strchr(conn->host.name, '@');
|
||||||
char *userpass = conn->host.name;
|
char *login = conn->host.name;
|
||||||
|
|
||||||
user[0] =0; /* to make everything well-defined */
|
user[0] = 0; /* to make everything well-defined */
|
||||||
passwd[0]=0;
|
passwd[0] = 0;
|
||||||
|
options[0] = 0;
|
||||||
|
|
||||||
/* We will now try to extract the
|
/* We will now try to extract the
|
||||||
* possible user+password pair in a string like:
|
* possible login information in a string like:
|
||||||
* ftp://user:password@ftp.my.site:8021/README */
|
* ftp://user:password@ftp.my.site:8021/README */
|
||||||
if(ptr != NULL) {
|
if(ptr) {
|
||||||
/* there's a user+password given here, to the left of the @ */
|
/* There's login information to the left of the @ */
|
||||||
|
|
||||||
conn->host.name = ++ptr;
|
conn->host.name = ++ptr;
|
||||||
|
|
||||||
@@ -4369,46 +4401,183 @@ static CURLcode parse_url_userpass(struct SessionHandle *data,
|
|||||||
* set user/passwd, but doing that first adds more cases here :-(
|
* set user/passwd, but doing that first adds more cases here :-(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conn->bits.userpwd_in_url = TRUE;
|
|
||||||
if(data->set.use_netrc != CURL_NETRC_REQUIRED) {
|
if(data->set.use_netrc != CURL_NETRC_REQUIRED) {
|
||||||
/* We could use the one in the URL */
|
/* We could use the login information in the URL so extract it */
|
||||||
|
result = parse_login_details(login, ptr - login - 1,
|
||||||
|
&userp, &passwdp, &optionsp);
|
||||||
|
if(!result) {
|
||||||
|
if(userp) {
|
||||||
|
char *newname;
|
||||||
|
|
||||||
|
/* We have a user in the URL */
|
||||||
|
conn->bits.userpwd_in_url = TRUE;
|
||||||
conn->bits.user_passwd = TRUE; /* enable user+password */
|
conn->bits.user_passwd = TRUE; /* enable user+password */
|
||||||
|
|
||||||
if(*userpass != ':') {
|
/* Decode the user */
|
||||||
/* the name is given, get user+password */
|
newname = curl_easy_unescape(data, userp, 0, NULL);
|
||||||
sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:@]:"
|
|
||||||
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]",
|
|
||||||
user, passwd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* no name given, get the password only */
|
|
||||||
sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", passwd);
|
|
||||||
|
|
||||||
if(user[0]) {
|
|
||||||
char *newname=curl_easy_unescape(data, user, 0, NULL);
|
|
||||||
if(!newname)
|
if(!newname)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if(strlen(newname) < MAX_CURL_USER_LENGTH)
|
if(strlen(newname) < MAX_CURL_USER_LENGTH)
|
||||||
strcpy(user, newname);
|
strcpy(user, newname);
|
||||||
|
|
||||||
/* if the new name is longer than accepted, then just use
|
|
||||||
the unconverted name, it'll be wrong but what the heck */
|
|
||||||
free(newname);
|
free(newname);
|
||||||
}
|
}
|
||||||
if(passwd[0]) {
|
|
||||||
/* we have a password found in the URL, decode it! */
|
if(passwdp) {
|
||||||
char *newpasswd=curl_easy_unescape(data, passwd, 0, NULL);
|
/* We have a password in the URL so decode it */
|
||||||
|
char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
|
||||||
if(!newpasswd)
|
if(!newpasswd)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
|
if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
|
||||||
strcpy(passwd, newpasswd);
|
strcpy(passwd, newpasswd);
|
||||||
|
|
||||||
free(newpasswd);
|
free(newpasswd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(optionsp) {
|
||||||
|
/* We have an options list in the URL so decode it */
|
||||||
|
char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
|
||||||
|
if(!newoptions)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
|
||||||
|
strcpy(options, newoptions);
|
||||||
|
|
||||||
|
free(newoptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CURLE_OK;
|
|
||||||
|
Curl_safefree(userp);
|
||||||
|
Curl_safefree(passwdp);
|
||||||
|
Curl_safefree(optionsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse_login_details()
|
||||||
|
*
|
||||||
|
* This is used to parse a login string for user name, password and options in
|
||||||
|
* the following formats:
|
||||||
|
*
|
||||||
|
* user
|
||||||
|
* user:password
|
||||||
|
* user:password;options
|
||||||
|
* user;options
|
||||||
|
* user;options:password
|
||||||
|
* :password
|
||||||
|
* :password;options
|
||||||
|
* ;options
|
||||||
|
* ;options:password
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* login [in] - The login string.
|
||||||
|
* len [in] - The length of the login string.
|
||||||
|
* userp [in/out] - The address where a pointer to newly allocated memory
|
||||||
|
* holding the user will be stored upon completion.
|
||||||
|
* passdwp [in/out] - The address where a pointer to newly allocated memory
|
||||||
|
* holding the password will be stored upon completion.
|
||||||
|
* optionsp [in/out] - The address where a pointer to newly allocated memory
|
||||||
|
* holding the options will be stored upon completion.
|
||||||
|
*
|
||||||
|
* Returns CURLE_OK on success.
|
||||||
|
*/
|
||||||
|
static CURLcode parse_login_details(const char *login, const size_t len,
|
||||||
|
char **userp, char **passwdp,
|
||||||
|
char **optionsp)
|
||||||
|
{
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
char *ubuf = NULL;
|
||||||
|
char *pbuf = NULL;
|
||||||
|
char *obuf = NULL;
|
||||||
|
const char *psep = NULL;
|
||||||
|
const char *osep = NULL;
|
||||||
|
size_t ulen;
|
||||||
|
size_t plen;
|
||||||
|
size_t olen;
|
||||||
|
|
||||||
|
/* Attempt to find the password separator */
|
||||||
|
if(passwdp) {
|
||||||
|
psep = strchr(login, ':');
|
||||||
|
|
||||||
|
/* Within the constraint of the login string */
|
||||||
|
if(psep >= login + len)
|
||||||
|
psep = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to find the options separator */
|
||||||
|
if(optionsp) {
|
||||||
|
osep = strchr(login, ';');
|
||||||
|
|
||||||
|
/* Within the constraint of the login string */
|
||||||
|
if(osep >= login + len)
|
||||||
|
osep = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the portion lengths */
|
||||||
|
ulen = (psep ?
|
||||||
|
(size_t)(osep && psep > osep ? osep - login : psep - login) :
|
||||||
|
(osep ? (size_t)(osep - login) : len));
|
||||||
|
plen = (psep ?
|
||||||
|
(osep && osep > psep ? (size_t)(osep - psep) :
|
||||||
|
(size_t)(login + len - psep)) - 1 : 0);
|
||||||
|
olen = (osep ?
|
||||||
|
(psep && psep > osep ? (size_t)(psep - osep) :
|
||||||
|
(size_t)(login + len - osep)) - 1 : 0);
|
||||||
|
|
||||||
|
/* Allocate the user portion buffer */
|
||||||
|
if(userp && ulen) {
|
||||||
|
ubuf = malloc(ulen + 1);
|
||||||
|
if(!ubuf)
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the password portion buffer */
|
||||||
|
if(!result && passwdp && plen) {
|
||||||
|
pbuf = malloc(plen + 1);
|
||||||
|
if(!pbuf)
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the options portion buffer */
|
||||||
|
if(!result && optionsp && olen) {
|
||||||
|
obuf = malloc(olen + 1);
|
||||||
|
if(!obuf)
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
/* Store the user portion if necessary */
|
||||||
|
if(ubuf) {
|
||||||
|
memcpy(ubuf, login, ulen);
|
||||||
|
ubuf[ulen] = '\0';
|
||||||
|
Curl_safefree(*userp);
|
||||||
|
*userp = ubuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the password portion if necessary */
|
||||||
|
if(pbuf) {
|
||||||
|
memcpy(pbuf, psep + 1, plen);
|
||||||
|
pbuf[plen] = '\0';
|
||||||
|
Curl_safefree(*passwdp);
|
||||||
|
*passwdp = pbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the options portion if necessary */
|
||||||
|
if(obuf) {
|
||||||
|
memcpy(obuf, osep + 1, olen);
|
||||||
|
obuf[olen] = '\0';
|
||||||
|
Curl_safefree(*optionsp);
|
||||||
|
*optionsp = obuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
@@ -4531,20 +4700,26 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Override a user name and password from the URL with that in the
|
* Override the login details from the URL with that in the CURLOPT_USERPWD
|
||||||
* CURLOPT_USERPWD option or a .netrc file, if applicable.
|
* option or a .netrc file, if applicable.
|
||||||
*/
|
*/
|
||||||
static void override_userpass(struct SessionHandle *data,
|
static void override_login(struct SessionHandle *data,
|
||||||
struct connectdata *conn,
|
struct connectdata *conn,
|
||||||
char *user, char *passwd)
|
char *user, char *passwd, char *options)
|
||||||
{
|
{
|
||||||
if(data->set.str[STRING_USERNAME] != NULL) {
|
if(data->set.str[STRING_USERNAME]) {
|
||||||
strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH);
|
strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH);
|
||||||
user[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
|
user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||||
}
|
}
|
||||||
if(data->set.str[STRING_PASSWORD] != NULL) {
|
|
||||||
|
if(data->set.str[STRING_PASSWORD]) {
|
||||||
strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH);
|
strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH);
|
||||||
passwd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
|
passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->set.str[STRING_OPTIONS]) {
|
||||||
|
strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH);
|
||||||
|
options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->bits.netrc = FALSE;
|
conn->bits.netrc = FALSE;
|
||||||
@@ -4570,32 +4745,48 @@ static void override_userpass(struct SessionHandle *data,
|
|||||||
/*
|
/*
|
||||||
* Set password so it's available in the connection.
|
* Set password so it's available in the connection.
|
||||||
*/
|
*/
|
||||||
static CURLcode set_userpass(struct connectdata *conn,
|
static CURLcode set_login(struct connectdata *conn,
|
||||||
const char *user, const char *passwd)
|
const char *user, const char *passwd,
|
||||||
|
const char *options)
|
||||||
{
|
{
|
||||||
/* If our protocol needs a password and we have none, use the defaults */
|
CURLcode result = CURLE_OK;
|
||||||
if((conn->handler->flags & PROTOPT_NEEDSPWD) &&
|
|
||||||
!conn->bits.user_passwd) {
|
|
||||||
|
|
||||||
|
/* If our protocol needs a password and we have none, use the defaults */
|
||||||
|
if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
|
||||||
|
/* Store the default user */
|
||||||
conn->user = strdup(CURL_DEFAULT_USER);
|
conn->user = strdup(CURL_DEFAULT_USER);
|
||||||
|
|
||||||
|
/* Store the default password */
|
||||||
if(conn->user)
|
if(conn->user)
|
||||||
conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
|
conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
|
||||||
else
|
else
|
||||||
conn->passwd = NULL;
|
conn->passwd = NULL;
|
||||||
|
|
||||||
/* This is the default password, so DON'T set conn->bits.user_passwd */
|
/* This is the default password, so DON'T set conn->bits.user_passwd */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* store user + password, zero-length if not set */
|
/* Store the user, zero-length if not set */
|
||||||
conn->user = strdup(user);
|
conn->user = strdup(user);
|
||||||
|
|
||||||
|
/* Store the password (only if user is present), zero-length if not set */
|
||||||
if(conn->user)
|
if(conn->user)
|
||||||
conn->passwd = strdup(passwd);
|
conn->passwd = strdup(passwd);
|
||||||
else
|
else
|
||||||
conn->passwd = NULL;
|
conn->passwd = NULL;
|
||||||
}
|
}
|
||||||
if(!conn->user || !conn->passwd)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
return CURLE_OK;
|
if(!conn->user || !conn->passwd)
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* Store the options, null if not set */
|
||||||
|
if(!result && options[0]) {
|
||||||
|
conn->options = strdup(options);
|
||||||
|
|
||||||
|
if(!conn->options)
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
@@ -4761,12 +4952,13 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
struct connectdata **in_connect,
|
struct connectdata **in_connect,
|
||||||
bool *async)
|
bool *async)
|
||||||
{
|
{
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct connectdata *conn;
|
struct connectdata *conn;
|
||||||
struct connectdata *conn_temp = NULL;
|
struct connectdata *conn_temp = NULL;
|
||||||
size_t urllen;
|
size_t urllen;
|
||||||
char user[MAX_CURL_USER_LENGTH];
|
char user[MAX_CURL_USER_LENGTH];
|
||||||
char passwd[MAX_CURL_PASSWORD_LENGTH];
|
char passwd[MAX_CURL_PASSWORD_LENGTH];
|
||||||
|
char options[MAX_CURL_OPTIONS_LENGTH];
|
||||||
bool reuse;
|
bool reuse;
|
||||||
char *proxy = NULL;
|
char *proxy = NULL;
|
||||||
bool prot_missing = FALSE;
|
bool prot_missing = FALSE;
|
||||||
@@ -4835,7 +5027,8 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
conn->host.name = conn->host.rawalloc;
|
conn->host.name = conn->host.rawalloc;
|
||||||
conn->host.name[0] = 0;
|
conn->host.name[0] = 0;
|
||||||
|
|
||||||
result = parseurlandfillconn(data, conn, &prot_missing, user, passwd);
|
result = parseurlandfillconn(data, conn, &prot_missing, user, passwd,
|
||||||
|
options);
|
||||||
if(result != CURLE_OK)
|
if(result != CURLE_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -5010,6 +5203,9 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
-1, NULL); /* no upload */
|
-1, NULL); /* no upload */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* since we skip do_init() */
|
||||||
|
Curl_speedinit(data);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5028,12 +5224,9 @@ static CURLcode create_conn(struct SessionHandle *data,
|
|||||||
if(result != CURLE_OK)
|
if(result != CURLE_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/*************************************************************
|
/* Check for overridden login details and set them accordingly */
|
||||||
* Check for an overridden user name and password, then set it
|
override_login(data, conn, user, passwd, options);
|
||||||
* for use
|
result = set_login(conn, user, passwd, options);
|
||||||
*************************************************************/
|
|
||||||
override_userpass(data, conn, user, passwd);
|
|
||||||
result = set_userpass(conn, user, passwd);
|
|
||||||
if(result != CURLE_OK)
|
if(result != CURLE_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ struct curl_schannel_cred {
|
|||||||
CredHandle cred_handle;
|
CredHandle cred_handle;
|
||||||
TimeStamp time_stamp;
|
TimeStamp time_stamp;
|
||||||
int refcount;
|
int refcount;
|
||||||
|
bool cached;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct curl_schannel_ctxt {
|
struct curl_schannel_ctxt {
|
||||||
@@ -324,6 +325,7 @@ struct ssl_connect_data {
|
|||||||
#ifdef USE_AXTLS
|
#ifdef USE_AXTLS
|
||||||
SSL_CTX* ssl_ctx;
|
SSL_CTX* ssl_ctx;
|
||||||
SSL* ssl;
|
SSL* ssl;
|
||||||
|
ssl_connect_state connecting_state;
|
||||||
#endif /* USE_AXTLS */
|
#endif /* USE_AXTLS */
|
||||||
#ifdef USE_SCHANNEL
|
#ifdef USE_SCHANNEL
|
||||||
struct curl_schannel_cred *cred;
|
struct curl_schannel_cred *cred;
|
||||||
@@ -859,6 +861,7 @@ struct connectdata {
|
|||||||
|
|
||||||
char *user; /* user name string, allocated */
|
char *user; /* user name string, allocated */
|
||||||
char *passwd; /* password string, allocated */
|
char *passwd; /* password string, allocated */
|
||||||
|
char *options; /* options string, allocated */
|
||||||
|
|
||||||
char *proxyuser; /* proxy user name string, allocated */
|
char *proxyuser; /* proxy user name string, allocated */
|
||||||
char *proxypasswd; /* proxy password string, allocated */
|
char *proxypasswd; /* proxy password string, allocated */
|
||||||
@@ -1136,8 +1139,7 @@ typedef enum {
|
|||||||
* Session-data MUST be put in the connectdata struct and here. */
|
* Session-data MUST be put in the connectdata struct and here. */
|
||||||
#define MAX_CURL_USER_LENGTH 256
|
#define MAX_CURL_USER_LENGTH 256
|
||||||
#define MAX_CURL_PASSWORD_LENGTH 256
|
#define MAX_CURL_PASSWORD_LENGTH 256
|
||||||
#define MAX_CURL_USER_LENGTH_TXT "255"
|
#define MAX_CURL_OPTIONS_LENGTH 256
|
||||||
#define MAX_CURL_PASSWORD_LENGTH_TXT "255"
|
|
||||||
|
|
||||||
struct auth {
|
struct auth {
|
||||||
unsigned long want; /* Bitmask set to the authentication methods wanted by
|
unsigned long want; /* Bitmask set to the authentication methods wanted by
|
||||||
@@ -1352,6 +1354,7 @@ enum dupstring {
|
|||||||
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
|
STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */
|
||||||
STRING_USERNAME, /* <username>, if used */
|
STRING_USERNAME, /* <username>, if used */
|
||||||
STRING_PASSWORD, /* <password>, if used */
|
STRING_PASSWORD, /* <password>, if used */
|
||||||
|
STRING_OPTIONS, /* <options>, if used */
|
||||||
STRING_PROXYUSERNAME, /* Proxy <username>, if used */
|
STRING_PROXYUSERNAME, /* Proxy <username>, if used */
|
||||||
STRING_PROXYPASSWORD, /* Proxy <password>, if used */
|
STRING_PROXYPASSWORD, /* Proxy <password>, if used */
|
||||||
STRING_NOPROXY, /* List of hosts which should not use the proxy, if
|
STRING_NOPROXY, /* List of hosts which should not use the proxy, if
|
||||||
@@ -1562,6 +1565,7 @@ struct UserDefined {
|
|||||||
long socks5_gssapi_nec; /* flag to support nec socks5 server */
|
long socks5_gssapi_nec; /* flag to support nec socks5 server */
|
||||||
#endif
|
#endif
|
||||||
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
|
struct curl_slist *mail_rcpt; /* linked list of mail recipients */
|
||||||
|
bool sasl_ir; /* Enable/disable SASL initial response */
|
||||||
/* Common RTSP header options */
|
/* Common RTSP header options */
|
||||||
Curl_RtspReq rtspreq; /* RTSP request type */
|
Curl_RtspReq rtspreq; /* RTSP request type */
|
||||||
long rtspversion; /* like httpversion, for RTSP */
|
long rtspversion; /* like httpversion, for RTSP */
|
||||||
|
|||||||
4
maketgz
4
maketgz
@@ -9,7 +9,7 @@
|
|||||||
# | (__| |_| | _ <| |___
|
# | (__| |_| | _ <| |___
|
||||||
# \___|\___/|_| \_\_____|
|
# \___|\___/|_| \_\_____|
|
||||||
#
|
#
|
||||||
# Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
# Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
#
|
#
|
||||||
# This software is licensed as described in the file COPYING, which
|
# This software is licensed as described in the file COPYING, which
|
||||||
# you should have received as part of this distribution. The terms
|
# you should have received as part of this distribution. The terms
|
||||||
@@ -142,7 +142,7 @@ make -s dist VERSION=$version
|
|||||||
|
|
||||||
bzip2="curl-$version.tar.bz2"
|
bzip2="curl-$version.tar.bz2"
|
||||||
echo "Generating $bzip2"
|
echo "Generating $bzip2"
|
||||||
gzip -dc $targz | bzip2 --best - > $bzip2
|
gzip -dc $targz | bzip2 --best > $bzip2
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ CFLAGS += -d_WIN32_WINNT=0x0501 -dENABLE_IPV6
|
|||||||
!ifdef %zlib_root
|
!ifdef %zlib_root
|
||||||
ZLIB_ROOT = $(%zlib_root)
|
ZLIB_ROOT = $(%zlib_root)
|
||||||
!else
|
!else
|
||||||
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.7
|
ZLIB_ROOT = ..$(DS)..$(DS)zlib-1.2.8
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
!ifdef %libssh2_root
|
!ifdef %libssh2_root
|
||||||
|
|||||||
@@ -66,6 +66,15 @@ curl_LDFLAGS = @LIBMETALINK_LDFLAGS@
|
|||||||
curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMETALINK_CPPFLAGS)
|
curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMETALINK_CPPFLAGS)
|
||||||
curl_DEPENDENCIES = $(top_builddir)/lib/libcurl.la
|
curl_DEPENDENCIES = $(top_builddir)/lib/libcurl.la
|
||||||
|
|
||||||
|
# if unit tests are enabled, build a static library to link them with
|
||||||
|
if BUILD_UNITTESTS
|
||||||
|
noinst_LTLIBRARIES = libcurltool.la
|
||||||
|
libcurltool_la_CPPFLAGS = $(LIBMETALINK_CPPFLAGS) $(AM_CPPFLAGS)
|
||||||
|
libcurltool_la_CFLAGS = -DUNITTESTS
|
||||||
|
libcurltool_la_LDFLAGS = -static $(LINKFLAGS)
|
||||||
|
libcurltool_la_SOURCES = $(curl_SOURCES)
|
||||||
|
endif
|
||||||
|
|
||||||
BUILT_SOURCES = tool_hugehelp.c
|
BUILT_SOURCES = tool_hugehelp.c
|
||||||
CLEANFILES = tool_hugehelp.c
|
CLEANFILES = tool_hugehelp.c
|
||||||
# Use the C locale to ensure that only ASCII characters appear in the
|
# Use the C locale to ensure that only ASCII characters appear in the
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ BCCDIR = $(MAKEDIR)\..
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
!ifndef ZLIB_PATH
|
!ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ..\..\zlib-1.2.7
|
ZLIB_PATH = ..\..\zlib-1.2.8
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-spi-winidn
|
## Example: mingw32-make -f Makefile.m32 CFG=-zlib-ssl-spi-winidn
|
||||||
##
|
##
|
||||||
## Hint: you can also set environment vars to control the build, f.e.:
|
## Hint: you can also set environment vars to control the build, f.e.:
|
||||||
## set ZLIB_PATH=c:/zlib-1.2.7
|
## set ZLIB_PATH=c:/zlib-1.2.8
|
||||||
## set ZLIB=1
|
## set ZLIB=1
|
||||||
#
|
#
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
ifndef ZLIB_PATH
|
ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ../../zlib-1.2.7
|
ZLIB_PATH = ../../zlib-1.2.8
|
||||||
endif
|
endif
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
ifndef OPENSSL_PATH
|
ifndef OPENSSL_PATH
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ endif
|
|||||||
|
|
||||||
# Edit the path below to point to the base of your Zlib sources.
|
# Edit the path below to point to the base of your Zlib sources.
|
||||||
ifndef ZLIB_PATH
|
ifndef ZLIB_PATH
|
||||||
ZLIB_PATH = ../../zlib-1.2.7
|
ZLIB_PATH = ../../zlib-1.2.8
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Edit the path below to point to the base of your OpenSSL package.
|
# Edit the path below to point to the base of your OpenSSL package.
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ OPENSSL_PATH = ../../openssl-0.9.8y
|
|||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
!IFNDEF ZLIB_PATH
|
!IFNDEF ZLIB_PATH
|
||||||
ZLIB_PATH = ../../zlib-1.2.7
|
ZLIB_PATH = ../../zlib-1.2.8
|
||||||
!ENDIF
|
!ENDIF
|
||||||
|
|
||||||
!IFNDEF MACHINE
|
!IFNDEF MACHINE
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ struct Configurable {
|
|||||||
char *mail_from;
|
char *mail_from;
|
||||||
struct curl_slist *mail_rcpt;
|
struct curl_slist *mail_rcpt;
|
||||||
char *mail_auth;
|
char *mail_auth;
|
||||||
|
bool sasl_ir; /* Enable/disable SASL initial response */
|
||||||
bool proxytunnel;
|
bool proxytunnel;
|
||||||
bool ftp_append; /* APPE on ftp */
|
bool ftp_append; /* APPE on ftp */
|
||||||
bool mute; /* don't show messages, --silent given */
|
bool mute; /* don't show messages, --silent given */
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ static const struct LongShort aliases[]= {
|
|||||||
{"$H", "mail-auth", TRUE},
|
{"$H", "mail-auth", TRUE},
|
||||||
{"$I", "post303", FALSE},
|
{"$I", "post303", FALSE},
|
||||||
{"$J", "metalink", FALSE},
|
{"$J", "metalink", FALSE},
|
||||||
|
{"$K", "sasl-ir", FALSE},
|
||||||
{"0", "http1.0", FALSE},
|
{"0", "http1.0", FALSE},
|
||||||
{"1", "tlsv1", FALSE},
|
{"1", "tlsv1", FALSE},
|
||||||
{"2", "sslv2", FALSE},
|
{"2", "sslv2", FALSE},
|
||||||
@@ -285,6 +286,105 @@ static const struct feat feats[] = {
|
|||||||
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
|
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
|
||||||
|
* We allow ':' and '\' to be escaped by '\' so that we can use certificate
|
||||||
|
* nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
|
||||||
|
* for details. */
|
||||||
|
#ifndef UNITTESTS
|
||||||
|
static
|
||||||
|
#endif
|
||||||
|
void parse_cert_parameter(const char *cert_parameter,
|
||||||
|
char **certname,
|
||||||
|
char **passphrase)
|
||||||
|
{
|
||||||
|
size_t param_length = strlen(cert_parameter);
|
||||||
|
size_t span;
|
||||||
|
const char *param_place = NULL;
|
||||||
|
char *certname_place = NULL;
|
||||||
|
*certname = NULL;
|
||||||
|
*passphrase = NULL;
|
||||||
|
|
||||||
|
/* most trivial assumption: cert_parameter is empty */
|
||||||
|
if(param_length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* next less trivial: cert_parameter contains no colon nor backslash; this
|
||||||
|
* means no passphrase was given and no characters escaped */
|
||||||
|
if(!strpbrk(cert_parameter, ":\\")) {
|
||||||
|
*certname = strdup(cert_parameter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* deal with escaped chars; find unescaped colon if it exists */
|
||||||
|
certname_place = malloc(param_length + 1);
|
||||||
|
if(!certname_place)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*certname = certname_place;
|
||||||
|
param_place = cert_parameter;
|
||||||
|
while(*param_place) {
|
||||||
|
span = strcspn(param_place, ":\\");
|
||||||
|
strncpy(certname_place, param_place, span);
|
||||||
|
param_place += span;
|
||||||
|
certname_place += span;
|
||||||
|
/* we just ate all the non-special chars. now we're on either a special
|
||||||
|
* char or the end of the string. */
|
||||||
|
switch(*param_place) {
|
||||||
|
case '\0':
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
param_place++;
|
||||||
|
switch(*param_place) {
|
||||||
|
case '\0':
|
||||||
|
*certname_place++ = '\\';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
*certname_place++ = '\\';
|
||||||
|
param_place++;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
*certname_place++ = ':';
|
||||||
|
param_place++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*certname_place++ = '\\';
|
||||||
|
*certname_place++ = *param_place;
|
||||||
|
param_place++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
/* Since we live in a world of weirdness and confusion, the win32
|
||||||
|
dudes can use : when using drive letters and thus c:\file:password
|
||||||
|
needs to work. In order not to break compatibility, we still use : as
|
||||||
|
separator, but we try to detect when it is used for a file name! On
|
||||||
|
windows. */
|
||||||
|
#ifdef WIN32
|
||||||
|
if(param_place &&
|
||||||
|
(param_place == &cert_parameter[1]) &&
|
||||||
|
(cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
|
||||||
|
(ISALPHA(cert_parameter[0])) ) {
|
||||||
|
/* colon in the second column, followed by a backslash, and the
|
||||||
|
first character is an alphabetic letter:
|
||||||
|
|
||||||
|
this is a drive letter colon */
|
||||||
|
*certname_place++ = ':';
|
||||||
|
param_place++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* escaped colons and Windows drive letter colons were handled
|
||||||
|
* above; if we're still here, this is a separating colon */
|
||||||
|
param_place++;
|
||||||
|
if(strlen(param_place) > 0) {
|
||||||
|
*passphrase = strdup(param_place);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
*certname_place = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
ParameterError getparameter(char *flag, /* f or -long-flag */
|
ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||||
char *nextarg, /* NULL if unset */
|
char *nextarg, /* NULL if unset */
|
||||||
bool *usedarg, /* set to TRUE if the arg
|
bool *usedarg, /* set to TRUE if the arg
|
||||||
@@ -858,6 +958,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'K': /* --sasl-ir */
|
||||||
|
config->sasl_ir = TRUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '#': /* --progress-bar */
|
case '#': /* --progress-bar */
|
||||||
@@ -1203,30 +1306,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
break;
|
break;
|
||||||
default: /* certificate file */
|
default: /* certificate file */
|
||||||
{
|
{
|
||||||
char *ptr = strchr(nextarg, ':');
|
char *certname, *passphrase;
|
||||||
/* Since we live in a world of weirdness and confusion, the win32
|
parse_cert_parameter(nextarg, &certname, &passphrase);
|
||||||
dudes can use : when using drive letters and thus
|
Curl_safefree(config->cert);
|
||||||
c:\file:password needs to work. In order not to break
|
config->cert = certname;
|
||||||
compatibility, we still use : as separator, but we try to detect
|
if(passphrase) {
|
||||||
when it is used for a file name! On windows. */
|
Curl_safefree(config->key_passwd);
|
||||||
#ifdef WIN32
|
config->key_passwd = passphrase;
|
||||||
if(ptr &&
|
|
||||||
(ptr == &nextarg[1]) &&
|
|
||||||
(nextarg[2] == '\\' || nextarg[2] == '/') &&
|
|
||||||
(ISALPHA(nextarg[0])) )
|
|
||||||
/* colon in the second column, followed by a backslash, and the
|
|
||||||
first character is an alphabetic letter:
|
|
||||||
|
|
||||||
this is a drive letter colon */
|
|
||||||
ptr = strchr(&nextarg[3], ':'); /* find the next one instead */
|
|
||||||
#endif
|
|
||||||
if(ptr) {
|
|
||||||
/* we have a password too */
|
|
||||||
*ptr = '\0';
|
|
||||||
ptr++;
|
|
||||||
GetStr(&config->key_passwd, ptr);
|
|
||||||
}
|
}
|
||||||
GetStr(&config->cert, nextarg);
|
|
||||||
cleanarg(nextarg);
|
cleanarg(nextarg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,5 +45,11 @@ ParameterError getparameter(char *flag,
|
|||||||
bool *usedarg,
|
bool *usedarg,
|
||||||
struct Configurable *config);
|
struct Configurable *config);
|
||||||
|
|
||||||
|
#ifdef UNITTESTS
|
||||||
|
void parse_cert_parameter(const char *cert_parameter,
|
||||||
|
char **certname,
|
||||||
|
char **passphrase);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* HEADER_CURL_TOOL_GETPARAM_H */
|
#endif /* HEADER_CURL_TOOL_GETPARAM_H */
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ static const char *const helptext[] = {
|
|||||||
" --retry-delay SECONDS "
|
" --retry-delay SECONDS "
|
||||||
"When retrying, wait this many seconds between each",
|
"When retrying, wait this many seconds between each",
|
||||||
" --retry-max-time SECONDS Retry only within this period",
|
" --retry-max-time SECONDS Retry only within this period",
|
||||||
|
" --sasl-ir Enable initial response in SASL authentication"
|
||||||
" -S, --show-error "
|
" -S, --show-error "
|
||||||
"Show error. With -s, make curl show errors when they occur",
|
"Show error. With -s, make curl show errors when they occur",
|
||||||
" -s, --silent Silent mode. Don't output anything",
|
" -s, --silent Silent mode. Don't output anything",
|
||||||
|
|||||||
@@ -55,6 +55,9 @@
|
|||||||
int vms_show = 0;
|
int vms_show = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* if we build a static library for unit tests, there is no main() function */
|
||||||
|
#ifndef UNITTESTS
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
|
* Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are
|
||||||
* open before starting to run. Otherwise, the first three network
|
* open before starting to run. Otherwise, the first three network
|
||||||
@@ -118,3 +121,4 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ndef UNITTESTS */
|
||||||
|
|||||||
@@ -1320,6 +1320,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
if(config->mail_auth)
|
if(config->mail_auth)
|
||||||
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
|
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
|
||||||
|
|
||||||
|
/* new in 7.31.0 */
|
||||||
|
if(config->sasl_ir)
|
||||||
|
my_setopt(curl, CURLOPT_SASL_IR, (long)TRUE);
|
||||||
|
|
||||||
/* initialize retry vars for loop below */
|
/* initialize retry vars for loop below */
|
||||||
retry_sleep_default = (config->retry_delay) ?
|
retry_sleep_default = (config->retry_delay) ?
|
||||||
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
|
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -322,13 +322,19 @@ ParameterError str2offset(curl_off_t *val, const char *str)
|
|||||||
ParameterError checkpasswd(const char *kind, /* for what purpose */
|
ParameterError checkpasswd(const char *kind, /* for what purpose */
|
||||||
char **userpwd) /* pointer to allocated string */
|
char **userpwd) /* pointer to allocated string */
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *psep;
|
||||||
|
char *osep;
|
||||||
|
|
||||||
if(!*userpwd)
|
if(!*userpwd)
|
||||||
return PARAM_OK;
|
return PARAM_OK;
|
||||||
|
|
||||||
ptr = strchr(*userpwd, ':');
|
/* Attempt to find the password separator */
|
||||||
if(!ptr) {
|
psep = strchr(*userpwd, ':');
|
||||||
|
|
||||||
|
/* Attempt to find the options separator */
|
||||||
|
osep = strchr(*userpwd, ';');
|
||||||
|
|
||||||
|
if(!psep && **userpwd != ';') {
|
||||||
/* no password present, prompt for one */
|
/* no password present, prompt for one */
|
||||||
char passwd[256] = "";
|
char passwd[256] = "";
|
||||||
char prompt[256];
|
char prompt[256];
|
||||||
@@ -336,6 +342,9 @@ ParameterError checkpasswd(const char *kind, /* for what purpose */
|
|||||||
size_t userlen = strlen(*userpwd);
|
size_t userlen = strlen(*userpwd);
|
||||||
char *passptr;
|
char *passptr;
|
||||||
|
|
||||||
|
if(osep)
|
||||||
|
*osep = '\0';
|
||||||
|
|
||||||
/* build a nice-looking prompt */
|
/* build a nice-looking prompt */
|
||||||
curlx_msnprintf(prompt, sizeof(prompt),
|
curlx_msnprintf(prompt, sizeof(prompt),
|
||||||
"Enter %s password for user '%s':",
|
"Enter %s password for user '%s':",
|
||||||
@@ -345,6 +354,9 @@ ParameterError checkpasswd(const char *kind, /* for what purpose */
|
|||||||
getpass_r(prompt, passwd, sizeof(passwd));
|
getpass_r(prompt, passwd, sizeof(passwd));
|
||||||
passwdlen = strlen(passwd);
|
passwdlen = strlen(passwd);
|
||||||
|
|
||||||
|
if(osep)
|
||||||
|
*osep = ';';
|
||||||
|
|
||||||
/* extend the allocated memory area to fit the password too */
|
/* extend the allocated memory area to fit the password too */
|
||||||
passptr = realloc(*userpwd,
|
passptr = realloc(*userpwd,
|
||||||
passwdlen + 1 + /* an extra for the colon */
|
passwdlen + 1 + /* an extra for the colon */
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ For FTP/SMTP/POP/IMAP, these are supported:
|
|||||||
REPLY [command] [return value] [response string]
|
REPLY [command] [return value] [response string]
|
||||||
- Changes how the server responds to the [command]. [response string] is
|
- Changes how the server responds to the [command]. [response string] is
|
||||||
evaluated as a perl string, so it can contain embedded \r\n, for example.
|
evaluated as a perl string, so it can contain embedded \r\n, for example.
|
||||||
|
There's a special [command] named "welcome" (without quotes) which is the
|
||||||
|
string sent immediately on connect as a welcome.
|
||||||
COUNT [command] [num]
|
COUNT [command] [num]
|
||||||
- Do the REPLY change for [command] only [num] times and then go back to the
|
- Do the REPLY change for [command] only [num] times and then go back to the
|
||||||
built-in approach
|
built-in approach
|
||||||
@@ -255,7 +257,9 @@ data that is defined within the <reply><data></data></reply> section.
|
|||||||
If there's no test number found above, the HTTP test server will use the
|
If there's no test number found above, the HTTP test server will use the
|
||||||
number following the last dot in the given hostname (made so that a CONNECT
|
number following the last dot in the given hostname (made so that a CONNECT
|
||||||
can still pass on test number) so that "foo.bar.123" gets treated as test case
|
can still pass on test number) so that "foo.bar.123" gets treated as test case
|
||||||
123.
|
123. Alternatively, if an ipv6-address is provided to CONNECT, the last
|
||||||
|
hexadecimal group in the address will be used as the test numer! For example
|
||||||
|
the address "[1234::ff]" would be treated as test case 255.
|
||||||
|
|
||||||
Set type="perl" to write the test case as a perl script. It implies that
|
Set type="perl" to write the test case as a perl script. It implies that
|
||||||
there's no memory debugging and valgrind gets shut off for this test.
|
there's no memory debugging and valgrind gets shut off for this test.
|
||||||
@@ -314,8 +318,11 @@ Variables are substituted on the contents of the file as in the <command>
|
|||||||
section.
|
section.
|
||||||
</file>
|
</file>
|
||||||
|
|
||||||
<stdin>
|
<stdin [nonewline="yes"]>
|
||||||
Pass this given data on stdin to the tool.
|
Pass this given data on stdin to the tool.
|
||||||
|
|
||||||
|
If 'nonewline' is set, we will cut off the trailing newline of this given data
|
||||||
|
before comparing with the one actually received by the client
|
||||||
</stdin>
|
</stdin>
|
||||||
|
|
||||||
</client>
|
</client>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ EXTRA_DIST = ftpserver.pl httpserver.pl secureserver.pl runtests.pl getpart.pm \
|
|||||||
FILEFORMAT README stunnel.pem memanalyze.pl testcurl.pl valgrind.pm ftp.pm \
|
FILEFORMAT README stunnel.pem memanalyze.pl testcurl.pl valgrind.pm ftp.pm \
|
||||||
sshserver.pl sshhelp.pm testcurl.1 runtests.1 $(HTMLPAGES) $(PDFPAGES) \
|
sshserver.pl sshhelp.pm testcurl.1 runtests.1 $(HTMLPAGES) $(PDFPAGES) \
|
||||||
serverhelp.pm tftpserver.pl rtspserver.pl directories.pm symbol-scan.pl \
|
serverhelp.pm tftpserver.pl rtspserver.pl directories.pm symbol-scan.pl \
|
||||||
CMakeLists.txt mem-include-scan.pl valgrind.supp
|
CMakeLists.txt mem-include-scan.pl valgrind.supp http_pipe.py
|
||||||
|
|
||||||
# we have two variables here to make sure DIST_SUBDIRS won't get 'unit'
|
# we have two variables here to make sure DIST_SUBDIRS won't get 'unit'
|
||||||
# added twice as then targets such as 'distclean' misbehave and try to
|
# added twice as then targets such as 'distclean' misbehave and try to
|
||||||
@@ -66,7 +66,7 @@ endif
|
|||||||
perlcheck:
|
perlcheck:
|
||||||
@if ! test -x "$(PERL)"; then echo "No perl!"; exit 2; fi
|
@if ! test -x "$(PERL)"; then echo "No perl!"; exit 2; fi
|
||||||
|
|
||||||
test: perhcheck all
|
test: perlcheck all
|
||||||
$(TEST)
|
$(TEST)
|
||||||
|
|
||||||
quiet-test: perlcheck all
|
quiet-test: perlcheck all
|
||||||
|
|||||||
@@ -61,13 +61,15 @@ test626 test627 test628 test629 test630 test631 test632 test633 test634 \
|
|||||||
test635 test636 test637 test638 test639 \
|
test635 test636 test637 test638 test639 \
|
||||||
\
|
\
|
||||||
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
|
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
|
||||||
test709 test710 \
|
test709 test710 test711 test712 \
|
||||||
\
|
\
|
||||||
test800 test801 test802 test803 test804 test805 test806 test807 test808 \
|
test800 test801 test802 test803 test804 test805 test806 test807 test808 \
|
||||||
|
test809 \
|
||||||
\
|
\
|
||||||
test850 test851 test852 test853 test854 test855 test856 test857 \
|
test850 test851 test852 test853 test854 test855 test856 test857 \
|
||||||
\
|
\
|
||||||
test900 test901 test902 test903 test904 test905 test906 \
|
test900 test901 test902 test903 test904 test905 test906 test907 test908 \
|
||||||
|
test909 test910 test911 \
|
||||||
\
|
\
|
||||||
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
|
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
|
||||||
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
|
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
|
||||||
@@ -89,8 +91,9 @@ test1128 test1129 test1130 test1131 test1132 test1133 \
|
|||||||
\
|
\
|
||||||
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
|
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
|
||||||
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
|
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
|
||||||
test1216 test1217 test1218 \
|
test1216 test1217 test1218 test1219 \
|
||||||
test1220 test1221 test1222 test1223 \
|
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
|
||||||
|
test1228 test1229 test1230 \
|
||||||
\
|
\
|
||||||
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
|
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
|
||||||
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
|
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
|
||||||
@@ -103,13 +106,13 @@ test1356 test1357 test1358 test1359 test1360 test1361 test1362 test1363 \
|
|||||||
test1364 test1365 test1366 test1367 test1368 test1369 test1370 test1371 \
|
test1364 test1365 test1366 test1367 test1368 test1369 test1370 test1371 \
|
||||||
test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 \
|
test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 \
|
||||||
test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 \
|
test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 \
|
||||||
test1388 test1389 test1390 test1391 test1392 test1393 \
|
test1388 test1389 test1390 test1391 test1392 test1393 test1394 test1396 \
|
||||||
\
|
\
|
||||||
test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
|
test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
|
||||||
test1408 test1409 test1410 test1411 test1412 test1413 \
|
test1408 test1409 test1410 test1412 test1413 \
|
||||||
\
|
\
|
||||||
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
|
test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
|
||||||
test1508 test1509 test1510 \
|
test1508 test1509 test1510 test1511 \
|
||||||
\
|
\
|
||||||
test1900 test1901 test1902 test1903 \
|
test1900 test1901 test1902 test1903 \
|
||||||
\
|
\
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ FTP GET with type=A style ASCII URL using %20 codes
|
|||||||
USER anonymous
|
USER anonymous
|
||||||
PASS ftp@example.com
|
PASS ftp@example.com
|
||||||
PWD
|
PWD
|
||||||
CWD /path with spaces
|
CWD /
|
||||||
|
CWD path with spaces
|
||||||
CWD and things2
|
CWD and things2
|
||||||
EPSV
|
EPSV
|
||||||
TYPE A
|
TYPE A
|
||||||
|
|||||||
@@ -874,7 +874,7 @@ crypto
|
|||||||
HTTP proxy CONNECT auth Digest, large headers and data
|
HTTP proxy CONNECT auth Digest, large headers and data
|
||||||
</name>
|
</name>
|
||||||
<command>
|
<command>
|
||||||
http://test.remote.haxx.se.1060:%HTTPPORT/path/10600002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
|
http://test.remote.haxx.se.1060:8990/path/10600002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
|
||||||
</command>
|
</command>
|
||||||
</client>
|
</client>
|
||||||
|
|
||||||
@@ -884,17 +884,17 @@ http://test.remote.haxx.se.1060:%HTTPPORT/path/10600002 --proxy http://%HOSTIP:%
|
|||||||
^User-Agent: curl/.*
|
^User-Agent: curl/.*
|
||||||
</strip>
|
</strip>
|
||||||
<protocol>
|
<protocol>
|
||||||
CONNECT test.remote.haxx.se.1060:%HTTPPORT HTTP/1.1
|
CONNECT test.remote.haxx.se.1060:8990 HTTP/1.1
|
||||||
Host: test.remote.haxx.se.1060:%HTTPPORT
|
Host: test.remote.haxx.se.1060:8990
|
||||||
Proxy-Connection: Keep-Alive
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
CONNECT test.remote.haxx.se.1060:%HTTPPORT HTTP/1.1
|
CONNECT test.remote.haxx.se.1060:8990 HTTP/1.1
|
||||||
Host: test.remote.haxx.se.1060:%HTTPPORT
|
Host: test.remote.haxx.se.1060:8990
|
||||||
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1060:%HTTPPORT", response="e1fbed39c26f4efe284adc0e576ff638"
|
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1060:8990", response="e1fbed39c26f4efe284adc0e576ff638"
|
||||||
Proxy-Connection: Keep-Alive
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
GET /path/10600002 HTTP/1.1
|
GET /path/10600002 HTTP/1.1
|
||||||
Host: test.remote.haxx.se.1060:%HTTPPORT
|
Host: test.remote.haxx.se.1060:8990
|
||||||
Accept: */*
|
Accept: */*
|
||||||
|
|
||||||
</protocol>
|
</protocol>
|
||||||
|
|||||||
@@ -879,7 +879,7 @@ crypto
|
|||||||
HTTP proxy CONNECT auth Digest, large headers and chunked data
|
HTTP proxy CONNECT auth Digest, large headers and chunked data
|
||||||
</name>
|
</name>
|
||||||
<command>
|
<command>
|
||||||
http://test.remote.haxx.se.1061:%HTTPPORT/path/10610002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
|
http://test.remote.haxx.se.1061:8990/path/10610002 --proxy http://%HOSTIP:%HTTPPORT --proxy-user silly:person --proxy-digest --proxytunnel
|
||||||
</command>
|
</command>
|
||||||
</client>
|
</client>
|
||||||
|
|
||||||
@@ -889,17 +889,17 @@ http://test.remote.haxx.se.1061:%HTTPPORT/path/10610002 --proxy http://%HOSTIP:%
|
|||||||
^User-Agent: curl/.*
|
^User-Agent: curl/.*
|
||||||
</strip>
|
</strip>
|
||||||
<protocol>
|
<protocol>
|
||||||
CONNECT test.remote.haxx.se.1061:%HTTPPORT HTTP/1.1
|
CONNECT test.remote.haxx.se.1061:8990 HTTP/1.1
|
||||||
Host: test.remote.haxx.se.1061:%HTTPPORT
|
Host: test.remote.haxx.se.1061:8990
|
||||||
Proxy-Connection: Keep-Alive
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
CONNECT test.remote.haxx.se.1061:%HTTPPORT HTTP/1.1
|
CONNECT test.remote.haxx.se.1061:8990 HTTP/1.1
|
||||||
Host: test.remote.haxx.se.1061:%HTTPPORT
|
Host: test.remote.haxx.se.1061:8990
|
||||||
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1061:%HTTPPORT", response="4e23449fa93224834299e7282a70472c"
|
Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="test.remote.haxx.se.1061:8990", response="4e23449fa93224834299e7282a70472c"
|
||||||
Proxy-Connection: Keep-Alive
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
GET /path/10610002 HTTP/1.1
|
GET /path/10610002 HTTP/1.1
|
||||||
Host: test.remote.haxx.se.1061:%HTTPPORT
|
Host: test.remote.haxx.se.1061:8990
|
||||||
Accept: */*
|
Accept: */*
|
||||||
|
|
||||||
</protocol>
|
</protocol>
|
||||||
|
|||||||
49
tests/data/test1219
Normal file
49
tests/data/test1219
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
data
|
||||||
|
to
|
||||||
|
see
|
||||||
|
that FTP
|
||||||
|
works
|
||||||
|
so does it?
|
||||||
|
</data>
|
||||||
|
<servercmd>
|
||||||
|
REPLY welcome 230 welcome without password
|
||||||
|
</servercmd>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP with no user+password required (230 response)
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT/1219
|
||||||
|
</command>
|
||||||
|
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
PWD
|
||||||
|
EPSV
|
||||||
|
TYPE I
|
||||||
|
SIZE 1219
|
||||||
|
RETR 1219
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
49
tests/data/test1224
Normal file
49
tests/data/test1224
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
data
|
||||||
|
to
|
||||||
|
see
|
||||||
|
that FTP
|
||||||
|
works
|
||||||
|
so does it?
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP fetch a file from the root directory
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT//1224
|
||||||
|
</command>
|
||||||
|
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS ftp@example.com
|
||||||
|
PWD
|
||||||
|
CWD /
|
||||||
|
EPSV
|
||||||
|
TYPE I
|
||||||
|
SIZE 1224
|
||||||
|
RETR 1224
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
57
tests/data/test1225
Normal file
57
tests/data/test1225
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
data
|
||||||
|
to
|
||||||
|
see
|
||||||
|
that FTP
|
||||||
|
works
|
||||||
|
so does it?
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP fetch two files using absolute paths
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT//foo/1225 ftp://%HOSTIP:%FTPPORT//foo/bar/1225
|
||||||
|
</command>
|
||||||
|
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS ftp@example.com
|
||||||
|
PWD
|
||||||
|
CWD /
|
||||||
|
CWD foo
|
||||||
|
EPSV
|
||||||
|
TYPE I
|
||||||
|
SIZE 1225
|
||||||
|
RETR 1225
|
||||||
|
CWD /
|
||||||
|
CWD /
|
||||||
|
CWD foo
|
||||||
|
CWD bar
|
||||||
|
EPSV
|
||||||
|
SIZE 1225
|
||||||
|
RETR 1225
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
49
tests/data/test1226
Normal file
49
tests/data/test1226
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
data
|
||||||
|
to
|
||||||
|
see
|
||||||
|
that FTP
|
||||||
|
works
|
||||||
|
so does it?
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP fetch a file from the root directory with singlecwd
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT//1226 --ftp-method singlecwd
|
||||||
|
</command>
|
||||||
|
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS ftp@example.com
|
||||||
|
PWD
|
||||||
|
CWD /
|
||||||
|
EPSV
|
||||||
|
TYPE I
|
||||||
|
SIZE 1226
|
||||||
|
RETR 1226
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
48
tests/data/test1227
Normal file
48
tests/data/test1227
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
data
|
||||||
|
to
|
||||||
|
see
|
||||||
|
that FTP
|
||||||
|
works
|
||||||
|
so does it?
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP fetch a file from the root directory with nocwd
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT//1227 --ftp-method nocwd
|
||||||
|
</command>
|
||||||
|
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS ftp@example.com
|
||||||
|
PWD
|
||||||
|
EPSV
|
||||||
|
TYPE I
|
||||||
|
SIZE /1227
|
||||||
|
RETR /1227
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
54
tests/data/test1228
Normal file
54
tests/data/test1228
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTP
|
||||||
|
HTTP GET
|
||||||
|
cookies
|
||||||
|
cookie path
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Tue, 25 Sep 2001 19:37:44 GMT
|
||||||
|
Set-Cookie: path1=root; domain=.example.fake; path=/;
|
||||||
|
Set-Cookie: path2=depth1; domain=.example.fake; path=/hoge;
|
||||||
|
Content-Length: 34
|
||||||
|
|
||||||
|
This server says cookie path test
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
HTTP cookie path match
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
http://example.fake/hoge/1228 http://example.fake/hogege/ -b nonexisting -x %HOSTIP:%HTTPPORT
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET http://example.fake/hoge/1228 HTTP/1.1
|
||||||
|
Host: example.fake
|
||||||
|
Accept: */*
|
||||||
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
|
GET http://example.fake/hogege/ HTTP/1.1
|
||||||
|
Host: example.fake
|
||||||
|
Accept: */*
|
||||||
|
Proxy-Connection: Keep-Alive
|
||||||
|
Cookie: path1=root
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
82
tests/data/test1229
Normal file
82
tests/data/test1229
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTP
|
||||||
|
HTTP GET
|
||||||
|
HTTP Digest auth
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
HTTP/1.1 401 Authorization Required swsclose
|
||||||
|
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||||
|
WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
|
||||||
|
Content-Type: text/html; charset=iso-8859-1
|
||||||
|
Content-Length: 26
|
||||||
|
|
||||||
|
This is not the real page
|
||||||
|
</data>
|
||||||
|
|
||||||
|
# This is supposed to be returned when the server gets a
|
||||||
|
# Authorization: Digest line passed-in from the client
|
||||||
|
<data1000>
|
||||||
|
HTTP/1.1 200 OK swsclose
|
||||||
|
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||||
|
Content-Type: text/html; charset=iso-8859-1
|
||||||
|
Content-Length: 23
|
||||||
|
|
||||||
|
This IS the real page!
|
||||||
|
</data1000>
|
||||||
|
|
||||||
|
<datacheck>
|
||||||
|
HTTP/1.1 401 Authorization Required swsclose
|
||||||
|
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||||
|
WWW-Authenticate: Digest realm="testrealm", nonce="1053604145"
|
||||||
|
Content-Type: text/html; charset=iso-8859-1
|
||||||
|
Content-Length: 26
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK swsclose
|
||||||
|
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
|
||||||
|
Content-Type: text/html; charset=iso-8859-1
|
||||||
|
Content-Length: 23
|
||||||
|
|
||||||
|
This IS the real page!
|
||||||
|
</datacheck>
|
||||||
|
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
crypto
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
HTTP with Digest authorization with user name needing escape
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
http://%5cuser%22:password@%HOSTIP:%HTTPPORT/1229 --digest
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /1229 HTTP/1.1
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
GET /1229 HTTP/1.1
|
||||||
|
Authorization: Digest username="\\user\"", realm="testrealm", nonce="1053604145", uri="/1229", response="f2694d426040712584c156d3de72b8d6"
|
||||||
|
Host: %HOSTIP:%HTTPPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
79
tests/data/test1230
Normal file
79
tests/data/test1230
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTP
|
||||||
|
HTTP CONNECT
|
||||||
|
IPv6
|
||||||
|
</keywords>
|
||||||
|
|
||||||
|
</info>
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
|
||||||
|
<data>
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Content-Length: 9
|
||||||
|
|
||||||
|
mooooooo
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<connect>
|
||||||
|
HTTP/1.1 200 welcome dear
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
</connect>
|
||||||
|
|
||||||
|
<datacheck>
|
||||||
|
HTTP/1.1 200 welcome dear
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Content-Length: 9
|
||||||
|
|
||||||
|
mooooooo
|
||||||
|
</datacheck>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
ipv6
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
http-proxy
|
||||||
|
http-ipv6
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
HTTP CONNECT to IPv6 numerical address
|
||||||
|
</name>
|
||||||
|
# 0x4ce == 1230, the test number
|
||||||
|
<command>
|
||||||
|
-g http://[1234:1234:1234::4ce]:%HTTPPORT/wanted/page/1230 -p -x %HOSTIP:%HTTPPORT
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
CONNECT [1234:1234:1234::4ce]:%HTTPPORT HTTP/1.1
|
||||||
|
Host: [1234:1234:1234::4ce]:%HTTPPORT
|
||||||
|
Proxy-Connection: Keep-Alive
|
||||||
|
|
||||||
|
GET /wanted/page/1230 HTTP/1.1
|
||||||
|
Host: [1234:1234:1234::4ce]:8990
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
||||||
@@ -58,7 +58,6 @@ From: different
|
|||||||
To: another
|
To: another
|
||||||
|
|
||||||
body
|
body
|
||||||
|
|
||||||
.
|
.
|
||||||
</upload>
|
</upload>
|
||||||
<proxy>
|
<proxy>
|
||||||
|
|||||||
30
tests/data/test1394
Normal file
30
tests/data/test1394
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
unittest
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
none
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
unittest
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
unit test for parse_cert_parameter()
|
||||||
|
</name>
|
||||||
|
<tool>
|
||||||
|
unit1394
|
||||||
|
</tool>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
<verify>
|
||||||
|
<stdout mode="text">
|
||||||
|
</stdout>
|
||||||
|
</verify>
|
||||||
|
|
||||||
|
</testcase>
|
||||||
27
tests/data/test1396
Normal file
27
tests/data/test1396
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
unittest
|
||||||
|
curl_easy_escape
|
||||||
|
curl_easy_unescape
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
none
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
unittest
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
curl_easy_escape and curl_easy_unescape
|
||||||
|
</name>
|
||||||
|
<tool>
|
||||||
|
unit1310
|
||||||
|
</tool>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
</testcase>
|
||||||
@@ -38,7 +38,7 @@ smtp://%HOSTIP:%SMTPPORT/user --mail-rcpt 1406@foo --mail-rcpt 1406@foobar.examp
|
|||||||
<verify>
|
<verify>
|
||||||
<protocol>
|
<protocol>
|
||||||
EHLO user
|
EHLO user
|
||||||
MAIL FROM:<1406@from> SIZE=34
|
MAIL FROM:<1406@from> SIZE=38
|
||||||
RCPT TO:<1406@foo>
|
RCPT TO:<1406@foo>
|
||||||
RCPT TO:<1406@foobar.example>
|
RCPT TO:<1406@foobar.example>
|
||||||
DATA
|
DATA
|
||||||
@@ -49,7 +49,6 @@ From: different
|
|||||||
To: another
|
To: another
|
||||||
|
|
||||||
body
|
body
|
||||||
|
|
||||||
.
|
.
|
||||||
</upload>
|
</upload>
|
||||||
<file name="log/test1406.c" mode="text">
|
<file name="log/test1406.c" mode="text">
|
||||||
@@ -70,7 +69,7 @@ int main(int argc, char *argv[])
|
|||||||
slist1 = curl_slist_append(slist1, "1406@foobar.example");
|
slist1 = curl_slist_append(slist1, "1406@foobar.example");
|
||||||
|
|
||||||
hnd = curl_easy_init();
|
hnd = curl_easy_init();
|
||||||
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)34);
|
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)38);
|
||||||
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/user");
|
curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/user");
|
||||||
curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
|
curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
|
||||||
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
|
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
|
||||||
|
|||||||
62
tests/data/test1511
Normal file
62
tests/data/test1511
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTP
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
HTTP/1.1 200
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fakem
|
||||||
|
Last-Modified: Mon, 22 Apr 2013 17:45:05 GMT
|
||||||
|
Content-Type: text/html
|
||||||
|
Content-Length: 12
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
Hello World
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<datacheck>
|
||||||
|
HTTP/1.1 200
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fakem
|
||||||
|
Last-Modified: Mon, 22 Apr 2013 17:45:05 GMT
|
||||||
|
Content-Type: text/html
|
||||||
|
Content-Length: 12
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fakem
|
||||||
|
Last-Modified: Mon, 22 Apr 2013 17:45:05 GMT
|
||||||
|
Content-Type: text/html
|
||||||
|
Content-Length: 12
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
Hello World
|
||||||
|
</datacheck>
|
||||||
|
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
http
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
http
|
||||||
|
</features>
|
||||||
|
<tool>
|
||||||
|
lib1511
|
||||||
|
</tool>
|
||||||
|
<name>
|
||||||
|
HTTP GET time conditions in repeated requests
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
http://%HOSTIP:%HTTPPORT/1511
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
</testcase>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user