OpenSSL: multi interface handshake could hang

John-Mark Bell filed bug #3000052 that identified a problem (with
an associated patch) with the OpenSSL handshake state machine
when the multi interface is used:

Performing an https request using a curl multi handle and using
select or epoll to wait for events results in a hang. It appears
that the cause is the fix for bug #2958179, which makes
ossl_connect_common unconditionally return from the step 2 loop
when fetching from a multi handle.

When ossl_connect_step2 has completed, it updates
connssl->connecting_state to ssl_connect_3. ossl_connect_common
will then return to the caller, as a multi handle is in
use. Eventually, the client code will call curl_multi_fdset to
obtain an updated fdset to select or epoll on. For https
requests, curl_multi_fdset will cause https_getsock to be called.
https_getsock will only return a socket handle if the
connecting_state is ssl_connect_2_reading or
ssl_connect_2_writing.  Therefore, the client will never obtain a
valid fdset, and thus not drive the multi handle, resulting in a
hang.

(http://curl.haxx.se/bug/view.cgi?id=3000052)
This commit is contained in:
Daniel Stenberg 2010-05-14 22:34:10 +02:00
parent ea521cf617
commit 77cfeadfa6
3 changed files with 34 additions and 2 deletions

21
CHANGES
View File

@ -7,6 +7,27 @@
Changelog Changelog
Daniel Stenberg (14 May 2010) Daniel Stenberg (14 May 2010)
- John-Mark Bell filed bug #3000052 that identified a problem (with an
associated patch) with the OpenSSL handshake state machine when the multi
interface is used:
Performing an https request using a curl multi handle and using select or
epoll to wait for events results in a hang. It appears that the cause is the
fix for bug #2958179, which makes ossl_connect_common unconditionally return
from the step 2 loop when fetching from a multi handle.
When ossl_connect_step2 has completed, it updates connssl->connecting_state
to ssl_connect_3. ossl_connect_common will then return to the caller, as a
multi handle is in use. Eventually, the client code will call
curl_multi_fdset to obtain an updated fdset to select or epoll on. For https
requests, curl_multi_fdset will cause https_getsock to be called.
https_getsock will only return a socket handle if the connecting_state is
ssl_connect_2_reading or ssl_connect_2_writing. Therefore, the client will
never obtain a valid fdset, and thus not drive the multi handle, resulting
in a hang.
(http://curl.haxx.se/bug/view.cgi?id=3000052)
- Sebastian V reported bug #3000056 identifying a problem with redirect - Sebastian V reported bug #3000056 identifying a problem with redirect
following. It showed that when curl followed redirects it didn't properly following. It showed that when curl followed redirects it didn't properly
ignore the response body of the 30X response if that response was using ignore the response body of the 30X response if that response was using

View File

@ -29,6 +29,7 @@ This release includes the following bugfixes:
o multi interface missed storing connection time o multi interface missed storing connection time
o broken CRL support in libcurl-NSS o broken CRL support in libcurl-NSS
o ignore response-body on redirect even if compressed o ignore response-body on redirect even if compressed
o OpenSSL handshake state-machine for multi interface
This release includes the following known bugs: This release includes the following known bugs:
@ -39,6 +40,6 @@ advice from friends like these:
Rainer Canavan, Paul Howarth, Jerome Vouillon, Ruslan Gazizov, Yang Tse, Rainer Canavan, Paul Howarth, Jerome Vouillon, Ruslan Gazizov, Yang Tse,
Kamil Dudka, Alex Bligh, Ben Greear, Hoi-Ho Chan, Howard Chu, Dirk Manske, Kamil Dudka, Alex Bligh, Ben Greear, Hoi-Ho Chan, Howard Chu, Dirk Manske,
Pavel Raiskup Pavel Raiskup, John-Mark Bell
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

@ -2425,8 +2425,18 @@ ossl_connect_common(struct connectdata *conn,
/* socket is readable or writable */ /* socket is readable or writable */
} }
/* Run transaction, and return to the caller if it failed or if
* this connection is part of a multi handle and this loop would
* execute again. This permits the owner of a multi handle to
* abort a connection attempt before step2 has completed while
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
retcode = ossl_connect_step2(conn, sockindex); retcode = ossl_connect_step2(conn, sockindex);
if(retcode || (data->state.used_interface == Curl_if_multi)) if(retcode || (data->state.used_interface == Curl_if_multi &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
ssl_connect_2_writing == connssl->connecting_state)))
return retcode; return retcode;
} /* repeat step2 until all transactions are done. */ } /* repeat step2 until all transactions are done. */