diff --git a/CHANGES b/CHANGES index 680a09989e..effb877f3e 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,14 @@ Changelog +Daniel Stenberg (3 May 2008) +- Ben Van Hof filed bug report #1945240: "libcurl sometimes sends body twice + when using CURL_AUTH_ANY" (http://curl.haxx.se/bug/view.cgi?id=1945240). + The problem was that when libcurl rewound a stream meant for upload when it + would prepare for a second request, it could accidentally continue the + sending of the rewound data on the first request instead of on the second. + Ben also provided test case 1030 that verifies this fix. + Daniel Stenberg (3 May 2008) - Jean-Francois Bertrand reported a libcurl crash with CURLOPT_TCP_NODELAY since libcurl used getprotobyname() and that isn't thread-safe. We now diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 10d558787e..dbc291724c 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -28,6 +28,7 @@ This release includes the following bugfixes: circumstances (found when using curlftpfs) o CURLOPT_OPENSOCKETFUNCTION can now be used to create a unix domain socket o CURLOPT_TCP_NODELAY crash due to getprotobyname() use + o libcurl sometimes sent body twice when using CURLAUTH_ANY This release includes the following known bugs: @@ -48,6 +49,6 @@ advice from friends like these: Michal Marek, Daniel Fandrich, Scott Barrett, Alexey Simak, Daniel Black, Rafa Muyo, Andre Guibert de Bruet, Brock Noland, Sandor Feldi, Stefan Krause, - David Shaw, Norbert Frese, Bart Whiteley, Jean-Francois Bertrand + David Shaw, Norbert Frese, Bart Whiteley, Jean-Francois Bertrand, Ben Van Hof Thanks! (and sorry if I forgot to mention someone) diff --git a/lib/transfer.c b/lib/transfer.c index 0ebe196523..3337b130a7 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -228,9 +228,9 @@ checkhttpprefix(struct SessionHandle *data, } /* - * Curl_readrewind() rewinds the read stream. This typically (so far) only - * used for HTTP POST/PUT with multi-pass authentication when a sending was - * denied and a resend is necessary. + * Curl_readrewind() rewinds the read stream. This is typically used for HTTP + * POST/PUT with multi-pass authentication when a sending was denied and a + * resend is necessary. */ CURLcode Curl_readrewind(struct connectdata *conn) { @@ -238,6 +238,11 @@ CURLcode Curl_readrewind(struct connectdata *conn) conn->bits.rewindaftersend = FALSE; /* we rewind now */ + /* explicitly switch of sending data on this transfer now since we are about + to restart a new transfer and thus we want to avoid inadvertently sending + more data on the existing connection until the next request starts */ + data->req.keepon &= ~KEEP_WRITE; + /* We have sent away data. If not using CURLOPT_POSTFIELDS or CURLOPT_HTTPPOST, call app to rewind */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 7459c3e9a1..fe1f2b101c 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -50,7 +50,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \ test551 test552 test1016 test1017 test1018 test1019 test1020 test553 \ test1021 test1022 test1023 test309 test616 test617 test618 test619 \ test620 test621 test622 test623 test624 test625 test626 test627 test554 \ - test1024 test1025 test555 test1026 test1027 test1028 test1029 + test1024 test1025 test555 test1026 test1027 test1028 test1029 test1030 filecheck: @mkdir test-place; \ diff --git a/tests/data/test1030 b/tests/data/test1030 new file mode 100644 index 0000000000..d05a0927a2 --- /dev/null +++ b/tests/data/test1030 @@ -0,0 +1,109 @@ + + + +HTTP +HTTP PUT +HTTP Digest auth +--anyauth + + + +# Server-side + + +HTTP/1.1 401 Authorization Required +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +WWW-Authenticate: Blackmagic realm="gimme all yer s3cr3ts" +WWW-Authenticate: Basic realm="gimme all yer s3cr3ts" +WWW-Authenticate: Digest realm="gimme all yer s3cr3ts", nonce="11223344" +Content-Length: 26 +Content-Type: text/html; charset=iso-8859-1 + +This is not the real page + + +# This is supposed to be returned when the server gets a +# Authorization: Digest line passed-in from the client + +HTTP/1.1 200 OK +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +Content-Type: text/html; charset=iso-8859-1 +Content-Length: 23 +Connection: close + +This IS the real page! + + + +HTTP/1.1 401 Authorization Required +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +WWW-Authenticate: Blackmagic realm="gimme all yer s3cr3ts" +WWW-Authenticate: Basic realm="gimme all yer s3cr3ts" +WWW-Authenticate: Digest realm="gimme all yer s3cr3ts", nonce="11223344" +Content-Length: 26 +Content-Type: text/html; charset=iso-8859-1 + +HTTP/1.1 200 OK +Server: Apache/1.3.27 (Darwin) PHP/4.1.2 +Content-Type: text/html; charset=iso-8859-1 +Content-Length: 23 +Connection: close + +This IS the real page! + + + + +# Client-side + + +http + + +crypto + + +HTTP PUT with --anyauth authorization (picking Digest) + + +http://%HOSTIP:%HTTPPORT/1030 -T log/put1030 -u testuser:testpass --anyauth + + +This is data we upload with PUT +a second line +line three +four is the number of lines + + + +# Verify data after the test has been "shot" + + +^User-Agent:.* + + +PUT /1030 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* +Content-Length: 85 +Expect: 100-continue + +This is data we upload with PUT +a second line +line three +four is the number of lines +PUT /1030 HTTP/1.1 +Authorization: Digest username="testuser", realm="gimme all yer s3cr3ts", nonce="11223344", uri="/1030", response="01cb59db1ddaac246b072d5f5f0716d9" +User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 zlib/1.1.3 +Host: %HOSTIP:%HTTPPORT +Accept: */* +Content-Length: 85 +Expect: 100-continue + +This is data we upload with PUT +a second line +line three +four is the number of lines + + +