From 77cfeadfa6405c5808273f1d3cc8e89eb17e5f08 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 14 May 2010 22:34:10 +0200 Subject: 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) --- CHANGES | 21 +++++++++++++++++++++ RELEASE-NOTES | 3 ++- lib/ssluse.c | 12 +++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index ecb36c437..d895ebeb6 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,27 @@ Changelog 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 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 diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 83b682e98..37348f91f 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -29,6 +29,7 @@ This release includes the following bugfixes: o multi interface missed storing connection time o broken CRL support in libcurl-NSS o ignore response-body on redirect even if compressed + o OpenSSL handshake state-machine for multi interface 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, 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) diff --git a/lib/ssluse.c b/lib/ssluse.c index ce62605e8..01eba90db 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -2425,8 +2425,18 @@ ossl_connect_common(struct connectdata *conn, /* 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); - 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; } /* repeat step2 until all transactions are done. */ -- cgit v1.2.3